NWOWN
NWOWN

Reputation: 407

C# FileStream.Read doesn't read last block

I read binary file to hex by block.

It is diffrent when I use FileStream.Read and File.ReadAllBytes

  1. FileSteram.Read

    int limit = 0;
    if (openFileDlg.FileName.Length > 0)
    {
        fileName = openFileDlg.FileName;
        FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
        fsLen = (int)fs.Length;
        int count = 0;
        limit = 100;
        byte[] read_buff = new byte[limit];
        StringBuilder sb = new StringBuilder();
        while ( (count = fs.Read(read_buff, 0, limit)) > 0)
        {
             foreach (byte b in read_buff)
             {
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
             }
    
        }
        rtxb_bin.AppendText(sb.ToString() + "\n");
    }
    
  2. File.ReadAllBytes

    if (openFileDlg.FileName.Length > 0)
    {
            fileName = openFileDlg.FileName;
            byte[] fileBytes = File.ReadAllBytes(fileName);
            StringBuilder sb2 = new StringBuilder();
    
            foreach (byte b2 in fileBytes)
            {
                sb2.Append(Convert.ToString(b2, 16).PadLeft(2, '0'));
            }
            rtxb_allbin.AppendText(sb2.ToString());
     }
    

case 1, reasult is ...

    ........04c0020f00452a00421346108129844f2138448500208020250405250043188510812e0

and case 2 is

      .......04c0020f00452a00421346108129844f2138448500208020250405250043188510812e044f212cc48120c24125404f2069c2c0008bff35f8f401efbd17047

FileStream.Read doesn't read after '12e0' '44f212cc48120c24125404f2069c2c0008bff35f8f401efbd17047' is missing

How can I read all bytes using FileStream.Read?

Why FileStream.Read doesn't read last block?

Upvotes: 1

Views: 933

Answers (3)

Rimbik Ind
Rimbik Ind

Reputation: 1

   public static void ReadAndProcessLargeFile(string theFilename, long whereToStartReading = 0)
    {
        FileInfo info = new FileInfo(theFilename);
        long fileLength = info.Length;
        long timesToRead = (fileLength / megabyte);
        long ctr = 0;
        long timesRead = 0;

        FileStream fileStram = new FileStream(theFilename, FileMode.Open, FileAccess.Read);
        using (fileStram)
        {
            byte[] buffer = new byte[megabyte];

            fileStram.Seek(whereToStartReading, SeekOrigin.Begin);

            int bytesRead = 0;
            
            //bytesRead = fileStram.Read(buffer, 0, megabyte);
            //ctr = ctr + 1;

            while ((bytesRead = fileStram.Read(buffer, 0, megabyte)) > 0)
            {
                ProcessChunk(buffer, bytesRead);
                buffer = new byte[megabyte]; // This solves last read prob
            }

        }
    }

    private static void ProcessChunk(byte[] buffer, int bytesRead)
    {
        // Do the processing here
        string utfString = Encoding.UTF8.GetString(buffer, 0, bytesRead);
        Console.Write(utfString);
    }

Upvotes: 0

Evk
Evk

Reputation: 101493

Most likely it appears to you that it does not read last block. Suppose you have file of length 102. First iteration of you loop reads first 100 bytes, all is fine. But what happens on second (last) one? You read two bytes into read_buff, which is of length 100. Now that buffer contains 2 bytes of last block and 98 bytes of previous (first) block, because Read doesn't clear the buffer. Then you proceed with:

 foreach (byte b in read_buff)
 {
    sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
 }

In result, sb has 100 bytes of first block, 2 bytes of last block, and then again 98 bytes of first block. If you don't look too closely, it might appear that it just skipped last block, while in reality it duplicated part of the previous one.

To fix, use count (indicating how much bytes were really read into the buffer) to work only with valid part of read_buff:

for (int i = 0; i < count; i++) {
    sb.Append(Convert.ToString(read_buff[i], 16).PadLeft(2, '0'));
}

Upvotes: 3

Cristian Pereira
Cristian Pereira

Reputation: 21

You need update offset and count.

Sintaxis

public override int Read(
    byte[] array,
    int offset,
    int count
)

Example

public static byte[] ReadFile(string filePath)
{
  byte[] buffer;
  FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  try
  {
    int length = (int)fileStream.Length;  // get file length
    buffer = new byte[length];            // create buffer
    int count;                            // actual number of bytes read
    int sum = 0;                          // total number of bytes read

    // read until Read method returns 0 (end of the stream has been reached)
    while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
      sum += count;  // sum is a buffer offset for next reading
  }
  finally
  {
    fileStream.Close();
  }
  return buffer;
}

Reference

Upvotes: 0

Related Questions