如何从JAVA循环中的文件中读取固定的字节数?

时间:2013-09-15 11:02:06

标签: java file file-io filereader

我必须阅读一个fie,在每次迭代中我必须从文件中读取8个字节。例如,在第一次迭代中,我将读取前8个字节,然后在第二次迭代中读取8个,依此类推。如何在Java中完成?

public static byte[] toByteArray(File file) {
    long length = file.length();
    byte[] array = new byte[length];
    InputStream in = new FileInputStream(file);
    long offset = 0;
    while (offset < length) {
        int count = in.read(array, offset, (length - offset));
        offset += length;
    }
    in.close();
    return array;
}

我已经找到了这个,但我认为这段代码正在做的是完全读取文件并创建文件数据的字节数组。但是我需要在一次迭代中只准备好我需要的那么多字节。

5 个答案:

答案 0 :(得分:2)

您可以轻松地根据需要调整代码:添加偏移量和计数,并调用skip以超过最初的N字节,如下所示 -

public static byte[] toByteArray(File file, long start, long count) {
      long length = file.length();
      if (start >= length) return new byte[0];
      count = Math.min(count, length - start);
      byte[] array = new byte[count];
      InputStream in = new FileInputStream(file);
      in.skip(start);
      long offset = 0;
      while (offset < count) {
          int tmp = in.read(array, offset, (length - offset));
          offset += tmp;
      }
      in.close();
      return array;
}

答案 1 :(得分:2)

使用DataInput进行此类处理:

  private void process(File file) throws IOException {
    try (RandomAccessFile data = new RandomAccessFile(file, "r")) {
      byte[] eight = new byte[8];
      for (long i = 0, len = data.length() / 8; i < len; i++) {
        data.readFully(eight);
        // do something with the 8 bytes
      }
    }
  }

我使用的是RandomAccessFile,但DataInputStream是一种常见的选择。

答案 2 :(得分:0)

将代码分成小块,例如,读取一个字节块(在你的情况下是8个字节),你需要知道3件事:

  1. 在哪个文件中阅读
  2. 从哪里开始阅读
  3. 要读取的字节数/块的大小
  4. 将此视为一步将为您提供一个返回byte []数组的方法,将上述3个点作为参数,例如:

    private byte[] readByteBlock(InputStream in, int offset, int noBytes) throws IOException {
        byte[] result = new byte[noBytes];
        in.read(result, offset, noBytes);
        return result;
    }
    

    下一步是打开文件并为文件中的每个字节块调用此方法。您开始在零位置读取文件,调用该方法一次,对结果执行某些操作,并在position =(previousPos)+ blockSize处调用它。这段代码可以放在另一种方法中,例如:

    public byte[][] toByteArray(File file, int byteBlockSize) throws IOException {
    
        InputStream in = new FileInputStream(file);
        long noOfBlocks = (long) Math.ceil((double)file.length() / (double)byteBlockSize);
        byte[][] result = new byte[(int)noOfBlocks][byteBlockSize];
        int offset = 0;
        for(int i = 0; i < result.length; i++) {
            result[i] = readByteBlock(in, offset, byteBlockSize);
        }
        return result;
    }
    

    这将返回一个byte [] []数组,第一个索引为byteBlockNumber(前8个字节,后8个字节,第3个8个字节,......),第二个索引为每个字节:

    byte[0][0]: the first byte block's first byte
    byte[0][7]: the first byte block's second byte
    byte[1][2]: the second byte block, third byte
    etc..
    

    在上面的示例代码中,byte [] []数组初始化为:

    long noOfBlocks = (long) Math.ceil((double)file.length() / (double)byteBlockSize);
    byte[][] result = new byte[noOfBlocks][byteBlockSize];
    

    因此块的数量是文件中的总字节数除以字节块的大小(在您的示例中为8)。假设文件有9个字节且块大小为8,这将导致1,sth并舍入为1,因此您将没有空间用于最后一个字节,这就是为什么Math.ceil()用于舍入到任何分裂给出。 Math.ceil(9/8) - &gt; 2,这些2足以容纳第一个8字节的块,以及第二个块的最后一个字节。

答案 3 :(得分:0)

您可以使用以下代码读取具有起始偏移量和大小的内存块:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FileReadingUtilities
{
    public static byte[] readBytes(String file, int start, int size) throws IOException
    {
        Path filePath = Paths.get(file);
        long fileSize = Files.size(filePath);

        if(start < 0)
        {
            throw new IllegalArgumentException("The start may not be negative!");
        }

        if(size < 0)
        {
            throw new IllegalArgumentException("The size may not be negative!");
        }

        if (start + size > fileSize)
        {
            throw new IllegalArgumentException("Interval exceeds file size!");
        }

        byte[] readBytes = new byte[size];

        try (InputStream inputStream = new FileInputStream(filePath.toFile()))
        {
            long actuallySkipped = inputStream.skip(start);

            if (start != actuallySkipped)
            {
                throw new IllegalStateException("Error while skipping bytes ahead!");
            }

            int bytesReadCount = inputStream.read(readBytes, 0, size);
            if (bytesReadCount != size)
            {
                throw new IllegalStateException("Not enough bytes have been read!");
            }
        }

        return readBytes;
    }
}

性能更好,请使用MappedByteBuffer

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class FileReadingUtilities
{
    public static ByteBuffer getByteBuffer(String filePath, int start, int size) throws IOException
    {
        File binaryFile = new File(filePath);
        FileChannel binaryFileChannel = new RandomAccessFile(binaryFile, "r").getChannel();

        return binaryFileChannel.map(FileChannel.MapMode.READ_ONLY, start, size);
    }
}

可以使用ByteBuffer方法从array()访问字节数组。

答案 4 :(得分:0)

public static void main(String[] args) {
   File dir = new File("C:\\");
   int fixedNumber = n;
   if (dir.isDirectory()) {
      for (String file : dir.list()) {
         int sum = sumByteArray(new File(dir.getAbsoluteFile() + "\\" + file),fixedNumber);
      }
   }
}

private static int sumByteArray(File file, int fixedNumber) {
   FileInputStream fileInputStream = null;
   byte[] bFile = new byte[fixedNumber];
   int sum = 0;
   try {
      fileInputStream = new FileInputStream(file);
      fileInputStream.read(bFile);
      fileInputStream.close();
      for (Byte b : bFile) {
         sum += (int) b;
      }
   } 
   catch (Exception e) {
      e.printStackTrace();
   }
   return sum;
}