How to get string by FileStream.Position and length specified in c# - c#

I have function that searches for string in a large binary file and give its position to me.
How to implement a function that read that position and give me string after specific length.
As we do in String.Substring()
Here is the code I have so far.
public void example()
{
string match = "400000002532"; //This is 12 chars in hex of the string to search
byte[] matchBytes = StringToByteArray(match);
foreach (var jsFile in jsscan)
{
using (var fs = new FileStream(jsFile, FileMode.Open))
{
int i = 0;
int readByte;
while ((readByte = fs.ReadByte()) != -1)
{
if (matchBytes[i] == readByte)
{
i++;
}
else
{
i = 0;
}
if (i == matchBytes.Length)
{
Console.WriteLine("It found between {0} and {1}.",
fs.Position - matchBytes.Length, fs.Position);
break;
}
}
}
}
}
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
Example what I am searching is below
400000002532010953667A51E44BE5B6A59417B71F4B91BBE590B6AF6E84EF570C32C56400E05123B0A44AF389331E4B91B02E8980B85157F910D7238918A73012B6243F772F7B60E5A7CF6E8CB25374B8FF96311130AABD9F71A860C904C9F6AE9706E570CC0E881E997762710EDE8818CCC551BA05579D30C0D53CEBD9BAF0C2E557D7B9D37A9C94A8A9B5FA7FCF7973B0BDA88A06DE1AE357130E4A06018ABB0A1ABD818DABEB518649CF885953EE05564FD69F0E2F860175667C5FC84F1C97727CEA1C841BFA86A26BABA942E0275FAB2A8F78132E3A05404F0DCD02FD4E7CAD08B1FFD4C2184400F22F6EBC14857BCC2E2AF858BE20CBB807C3467A91E38F31901FD452B5F87F296174631980E039CAB58D97E8F91E3255DD7DEF3177D68A4943F629A70B421B1D6E53DC0D26A1B5EF7C6912F48E0842037FA72B17C18E11B93AEE4DDA0FFE6F217BD5DEB957B1C26169029DE4396103D1F89FA0856489B1958DE5C896DB8F27A24C21AC66BF2095E383DA5EC6DA7138FE82C62FDE9BEFF0308F507736F1B35B1CA083F6C96A6860889BDCCBC989E86F4FB1C483E71557369E7308450330AEF8C9A13A115E8A97642E4A0A4098F5BC04A096A22E5F97116B59AE17BCAEFD2A8B0BCB5341EC64CA3E474900D5A8A620448A6C97827C42332C4DD326572A3C5DB4DA1362F3C0012E1AA1B70C812DCCAEF74F67E94E907518CA31945DD56A61A7

If performance is not of huge concern, you could do the following, which is more easy and readable
using (var fs = new StreamReader(fileName))
{
var content = await fs.ReadToEndAsync();
var pos = content.IndexOf(matchBytes);
if (pos != -1)
{
Console.WriteLine($"Found # {pos}, {pos + matchBytes.Length}");
}
}

Assuming you know which Encoding is used to store characters in the Stream, try this function:
static string GetString(Stream stream, long position, int stringLength, Encoding encoding) {
int offset = 0;
int readByte;
byte[] buffer = new byte[stream.Length - position];
stream.Seek(position, SeekOrigin.Begin);
while ((readByte = stream.ReadByte()) != -1)
{
buffer[offset++] = (byte)readByte;
if (encoding.GetCharCount(buffer, 0, offset) == stringLength + 1)
{
return encoding.GetString(buffer, 0, offset - 1);
}
}
if (encoding.GetCharCount(buffer, 0, offset) == stringLength)
{
return encoding.GetString(buffer, 0, offset);
}
throw new Exception(string.Format("Stream doesn't contains {0} characters", stringLength));
}
For example, with your code and utf-16:
using (var fs = new FileStream(jsFile, FileMode.Open))
{
int i = 0;
int readByte;
while ((readByte = fs.ReadByte()) != -1)
{
if (matchBytes[i] == readByte)
{
i++;
}
else
{
i = 0;
}
if (i == matchBytes.Length)
{
Console.WriteLine("It found between {0} and {1}.",
fs.Position - matchBytes.Length, fs.Position);
//Desired string length in charachters
const int DESIRED_STRING_LENGTH = 5;
Console.WriteLine(GetString(fs, fs.Position, DESIRED_STRING_LENGTH, Encoding.Unicode));
break;
}
}
}

Related

Edit Wav File Samples for Increasing Amplitude using c#

I have the following c# code which reads a wave file into a byte array and then writes it into another array, creating a new wave file. I found it online and dont have much knowledge about it.
I want to change the values being written into the new array so that my amplitude is increased by let's say a value 'x' for the new wave file being generated.. Where and what should be the changes made?
private void ReadWavfiles(string fileName)
{
byte[] fa = File.ReadAllBytes(fileName);
int startByte = 0;
// look for data header
for (var x = 0; x < fa.Length; x++)
if (fa[x] == 'd' && fa[x + 1] == 'a' && fa[x + 2] == 't' && fa[x + 3] == 'a')
{
startByte = x + 8;
break;
}
var buff = new byte[fa.Length / 2];
var y = 0;
var length = fa.Length;
for (int s = startByte; s < length; s = s + 2)
buff[y++] = (byte)(fa[s + 1] * 0x100 + fa[s]);
write(buff, "D:\\as1.wav", "D:\\us1.wav");
WaveOut obj = new WaveOut();
obj.Init(new WaveFileReader("D:\\as1.wav"));
obj.Play();
}
private void write(byte[] buffer, string fileOut, string fileIn)
{
WaveFileReader reader = new WaveFileReader(fileIn);
int numChannels = reader.WaveFormat.Channels, sampleRate = reader.WaveFormat.SampleRate;
int BUFFER_SIZE = 1024 * 16;
using (WaveFileWriter writer = new WaveFileWriter(fileOut, new WaveFormat(sampleRate, 16, numChannels)))
{
int bytesRead;
while (true)
{
bytesRead = reader.Read(buffer, 0, BUFFER_SIZE);
if (bytesRead != 0)
writer.Write(buffer, 0, bytesRead);
else break;
}
writer.Close();
}
}

reading from two mono files and converting to one stero wav file- without the ability to use Naudion

I'm trying to read from two alaw/pcm files in the following way:
byte[] dlBuffer = null;
if (dlStream != null)
{
dlStream.Position = 0;
dlBuffer = new byte[dlStream.Length+1];
int readDL = dlStream.Read(dlBuffer, 0, dlBuffer.Length);
}
byte[] ulBuffer = null;
if (ulStream != null)
{
ulStream.Position = 0;
ulBuffer = new byte[ulStream.Length+1];
int readUL = ulStream.Read(ulBuffer, 0, ulBuffer.Length);
}
And then to save the buffers to one wav file:
private const int WAVE_HEADER_SIZE = 44;
private const int WAVE_BUFFER_SIZE = 2 * 1024 * 1024; // = 2,097,152
private bool SaveBufferToWave(string wavFileName, VoiceMetadata metadata,byte[] dlBuffer,byte[] ulBuffer)
{
if ((wavFileName == null) || (wavFileName.Length == 0) || (metadata == null))
return false;
FileStream fileStream = null;
bool success = true;
try
{
byte[] waveBuffer = new byte[WAVE_BUFFER_SIZE];
int bytesToWrite = 0;
int dlRead = 0, ulRead = 0;
//If we have DL & UL write stereo wav, else write mono wave
int channels = (metadata.DLExists && metadata.ULExists) ? 2 : 1;
int samples = (int)metadata.TotalTimeMS * (VoiceMetadata.SAMPLES_PER_SECOND / 1000);
fileStream = new FileStream(wavFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
BinaryWriter wrt = new BinaryWriter(fileStream);
wrt.Write(GetHeader(
WAVE_HEADER_SIZE + (samples) * (channels) * sizeof(short), sizeof(short) * 8,
channels,
8000));
if (channels == 2)
{
if (dlRead == 0)
{
dlRead = dlBuffer.Length;
}
if (ulRead == 0)
{
ulRead = ulBuffer.Length;
}
if ((dlRead != 0) && (ulRead != 0))
{
//Create the stero wave buffer
Array.Clear(waveBuffer, 0, waveBuffer.Length);
for (int i = 0; i < dlRead / 2; ++i)
{
waveBuffer[i * 4 + 0] = dlBuffer[i * 2];
waveBuffer[i * 4 + 1] = dlBuffer[i * 2 + 1];
}
for (int i = 0; i < ulRead / 2; ++i)
{
waveBuffer[i * 4 + 2] = ulBuffer[i * 2];
waveBuffer[i * 4 + 3] = ulBuffer[i * 2 + 1];
}
bytesToWrite = Math.Max(ulRead * 2, dlRead * 2);
dlRead = 0;
ulRead = 0;
}
else
bytesToWrite = 0;
}
else
{
//Create the mono wave buffer
if (metadata.ULExists)
{
Buffer.BlockCopy(ulBuffer, 0, waveBuffer, 0, ulBuffer.Length);
bytesToWrite = ulBuffer.Length;
}
else if (metadata.DLExists)
{
Buffer.BlockCopy(dlBuffer, 0, waveBuffer, 0, dlBuffer.Length);
bytesToWrite = dlBuffer.Length;
}
else
{
bytesToWrite = 0;
}
}
if (bytesToWrite > 0)
fileStream.Write(waveBuffer, 0, bytesToWrite);
Logger.Debug("File {0} was saved successfully in wav format.", wavFileName);
}
catch (Exception e)
{
Logger.Error("Failed saving file {0} in wav format, Exception: {1}.", wavFileName, e);
success = false;
}
finally
{
if (fileStream != null)
fileStream.Close();
}
return success;
}
Most of the times it works fine, but sometimes I get one of this two exceptions:
Failed saving file c:\Samples\WAV\24112014-095948.283.wav in wav format, Exception: System.ArgumentException: Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
Failed saving file c:\Samples\WAV\24112014-100742.409.wav in wav format, Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.
What can be the problem?

Remove range from byte array

I have a file in a byte[], and I need to remove 0x1000 bytes at every x offset (I have a list of offsets). I have some code to do it, but I'm wondering if there is a better way to do it;
private byte[] RemoveHashBlocks(byte[] fileArray, STFSExplorer stfs)
{
long startOffset = StartingOffset;
long endOffset = StartingOffset + Size;
List<long> hashBlockOffsets = new List<long>();
foreach (xBlockEntry block in stfs._stfsBlockEntry)
if (block.IsHashBlock && (block.BlockOffset >= startOffset && block.BlockOffset <= endOffset))
hashBlockOffsets.Add(block.BlockOffset - (hashBlockOffsets.Count * 0x1000));
byte[] newFileAray = new byte[fileArray.Length - (hashBlockOffsets.Count * 0x1000)];
for (int offset = 0; offset < fileArray.Length; offset++)
if (hashBlockOffsets[0] == offset)
{
offset += 0x1000;
hashBlockOffsets.RemoveAt(0);
}
else
newFileAray[offset] = fileArray[offset];
return newFileAray;
}
private byte[] RemoveHashBlocks(byte[] fileArray, STFSExplorer stfs)
{
long startOffset = StartingOffset;
long size = Size;
MemoryStream ms = new MemoryStream();
long lastBlockEnd = 0;
foreach (xBlockEntry block in stfs._stfsBlockEntry)
{
if (block.IsHashBlock)
{
long offset = block.BlockOffset - startOffset;
if (offset + 0x1000 > 0 && offset < size)
{
if (offset > lastBlockEnd)
{
ms.Write(fileArray, (int) lastBlockEnd,
(int) (offset - lastBlockEnd));
}
lastBlockEnd = offset + 0x1000;
}
}
}
if (lastBlockEnd < size)
{
ms.Write(fileArray, (int) lastBlockEnd, (int) (size - lastBlockEnd));
}
return ms.ToArray();
}
This assumes stfs._stfsBlockEntry is sorted by BlockOffset.

FileStream read ending prematurely

I have a function that strips a wav file from a video, then using FileStream I read from the wavefile. The problem is, the read function returns -1 (no more bytes to be read) prematurely. Its a 20 minute wav file, but only about 17.5 minutes are written.
In this function, I am mixing several wave files into a one large one. The problem is the filestream reader for the large wave file is ending too early. I can't figure out why.
Here is my code:
public void combineWaveFileData(object status)
{
//ProgressWindow progressWindow = status as ProgressWindow;
ExportProgressWindow exportProgressWindow = status as ExportProgressWindow;
string videoAudioFile = outfileName + ".temp";
int descriptionStartSample = 0;
int highestNumber = 0;
int extraSamplesFromExtendedDescription = 0;
const double VOLUME_VIDEO_FACTOR = 0.8; //controls video volume levels; won't be const as volume control will be added later
const double VOLUME_DESCRIPTION_FACTOR = 1.5; //controls description volume levels
double currentSample = 0; //keeps track of the current sample in the video audio track
byte[] videoAudioBuffer = new byte[4];//new byte[bitsPerSample / 8];
int sample = 0; //holds raw audio data sample
int videoReadStatus = 1;
int descriptionEndSample = 0;
byte[] buffer = new byte[4];
FileStream tempStream;
videoAudioStream = new FileStream(videoAudioFile, FileMode.Open, FileAccess.ReadWrite);
videoAudioStream.Seek(DATA_START_POS - 4, 0);
videoAudioStream.Read(buffer, 0, buffer.Length);
totalRawSoundDataBits = BitConverter.ToInt32(buffer, 0);
//totalRawSoundDataBits = videoAudioStream.Length;
videoAudioStream.Seek(24, 0);
videoAudioStream.Read(buffer, 0, 4);
int videoSampleRate = BitConverter.ToInt32(buffer, 0);
sampleRateHz = videoSampleRate;
outFileStream = new FileStream(outfileName, FileMode.Create, FileAccess.ReadWrite);
videoAudioStream.Seek(0, 0);
writeAudioFileHeader(outFileStream, videoAudioStream);
// videoAudioStream.Seek(0, 0); //reset video audio position to 0 (beginning)
convertStatus = false;
if (compatibilityIssue)
{
exportProgressWindow.Close();
return;
}
//calculate total length of extended description files
foreach (Description description in descriptionList)
{
if (description.IsExtendedDescription)
{
tempStream = new FileStream(description.getFilename(), FileMode.Open);
totalRawSoundDataBits += tempStream.Length - DATA_START_POS;
try
{
tempStream.Close();
tempStream.Dispose();
tempStream = null;
}
catch { }
}
WaveReader read = new WaveReader(File.OpenRead(description.getFilename()));
IntPtr oldFormat = read.ReadFormat();
WaveFormat waveformat = AudioCompressionManager.GetWaveFormat(oldFormat);
int descriptionSampleRateHz = waveformat.nSamplesPerSec;
read.Close();
string resampledFilename = description.getFilename();
if (descriptionSampleRateHz != sampleRateHz)
{
exportProgressWindow.SetText(".");
resampledFilename = convertSampleRate(description.getFilename(), sampleRateHz);
description.setFilename(resampledFilename);
}
}
for (int i = 0; i < descriptionList.Count; i++)
{
for (int j = 0; j < descriptionList.Count; j++)
{
Description tempDescription;
if (((Description)descriptionList[i]).getStart() < ((Description)descriptionList[j]).getStart())
{
tempDescription = (Description)descriptionList[j];
descriptionList[j] = descriptionList[i];
descriptionList[i] = tempDescription;
}
}
}
int k = 0;
while (videoReadStatus > 0)
{
try
{
Description description;
description = (Description)descriptionList[k];
descriptionStartSample = (int)Math.Truncate(sampleRateHz * description.getStart());
descriptionEndSample = (int)Math.Truncate(sampleRateHz * description.getEnd());
if (videoAudioStream.Position / 4 > descriptionStartSample )
{
double currentTime = videoAudioStream.Position / 4 / sampleRateHz;
Console.WriteLine(currentTime+ " " + description.getStart() + " " + description.getEnd());
if (k < descriptionList.Count - 1)
{
k++;
}
double percentage = Convert.ToDouble(k) / Convert.ToDouble(descriptionList.Count) * 100.0;
try
{
exportProgressWindow.Increment(percentage);
}
catch (Exception ex)
{
return;
}
buffer = new byte[4];
tempStream = new FileStream(description.getFilename(), FileMode.Open);
try
{
tempStream.Seek(44, 0); //to search for position 34; write: use writeSample()
int tempReadStatus = 1;
while (tempReadStatus > 0 && videoReadStatus > 0)//(currentSample < descriptionEndSample)
{
//If description isn't an extended description then mix the description with the video audio
if (!description.IsExtendedDescription)
{
videoReadStatus = videoAudioStream.Read(videoAudioBuffer, 0, 2);
tempReadStatus = tempStream.Read(buffer, 0, 2);
if (videoReadStatus == 0)
{
Console.WriteLine(currentTime);
int debug = 0;
}
if (tempReadStatus <= 0 || videoReadStatus <=0)
{
int deleteme = 0;
}
sample += (int)(((BitConverter.ToInt16(buffer, 0))* VOLUME_DESCRIPTION_FACTOR + (BitConverter.ToInt16(videoAudioBuffer, 0) * VOLUME_VIDEO_FACTOR)) / 2);
writeSample(sample);
sample = 0;
}
else
// If description is extended then only write the description samples
{
int tempStatus = 1;
while (tempReadStatus > 0)
{
tempReadStatus = tempStream.Read(buffer, 0, 2);
sample = (int)((BitConverter.ToInt16(buffer, 0)));// -((sample * (int)(BitConverter.ToInt16(buffer, 0))) / 65535); //Z = A+B-AB/65535 http://www.vttoth.com/CMS/index.php/technical-notes/68 //* VOLUME_DESCRIPTION_FACTOR);
writeSample(sample);
sample = 0;
}
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine("Debug 1: " + ex.Message);//MessageBox.Show(ex.Message);
}
finally
{
tempStream.Close();
tempStream.Dispose();
tempStream = null;
}
}
else
{
try
{
videoReadStatus = videoAudioStream.Read(videoAudioBuffer, 0, 2);
sample += (int)((BitConverter.ToInt16(videoAudioBuffer, 0)) * VOLUME_VIDEO_FACTOR) ;
if (videoReadStatus == 0)
{
int debug = 0;
}
writeSample(sample);
sample = 0;
convertStatus = true;
}
catch (Exception ex)
{
int test = 0;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.GetBaseException().ToString());
}
}
exportProgressWindow.SetText("\n\nLiveDescribe has successfully exported the file.");
try
{
closeStreams();
Control.CheckForIllegalCrossThreadCalls = false;
}
catch (Exception ex)
{
}
}

How can make my file reading class return an IEnumerable<byte[]> object

... that I can read into a BlockingCollection<byte[]> in the same way that System.IO.File.ReadLines() can be read into a BlockingCollection<string> in .net4.0?
You could use File.Open to get a FileStream, and then use FileStream.Read:
IEnumerable<byte[]> GetFileBytes(string filename)
{
var fsSource = File.Open(filename, FileMode.Open);
const int bytesToReadPerIteration = 100;
int numBytesToRead = (int)fsSource.Length;
int numBytesRead = 0;
while (numBytesToRead > 0)
{
byte[] bytes = new byte[Math.Min(bytesToReadPerIteration, numBytesToRead)];
// Read may return anything from 0 to numBytesToRead.
int n = fsSource.Read(bytes, numBytesRead, numBytesToRead);
// Break when the end of the file is reached.
if (n == 0)
break;
if (n != bytes.Length)
{
byte[] tmp = new byte[n];
Array.Copy(bytes, tmp, n);
bytes = tmp;
}
yield return bytes;
numBytesRead += n;
numBytesToRead -= n;
}
fsSource.Close();
}
Sounds like "yield return" is what you're looking for:
static IEnumerable<byte> GetBytes()
{
byte[] bytes = new byte[10];
// simple initialization of the array, replace with your I/O here if blocking
for (byte x = 0; x < bytes.Length; x++)
{
bytes[x] = x;
}
// this generates the IEnumerable<byte>.
// Replace "bytes[x]" with an I/O operation
// that returns one byte if you want to allow data to flow as available through
// the IEnumerable<byte>
for (int x = 0; x < bytes.Length; x++)
{
yield return bytes[x];
}
}
public IEnumerable<Byte[]> ReadFile(String fileName)
{
using (FileStream file = new FileStream(fileName, FileMode.Open))
{
using (StreamReader reader = new StreamReader(file))
{
while (reader.Peek() >= 0)
{
String line = reader.ReadLine();
yield return System.Text.Encoding.Default.GetBytes(line);
}
}
}
}

Categories