如何在JAVA循环中从文件中读取固定数量的字节?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18811608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Read fixed number of bytes from a file in a loop in JAVA?
提问by Usama Sarwar
I have to read a fie where in every iteration I have to read 8 bytes form the file. For example in first iteration I'll read first 8 bytes and in second iteration next 8 and so on. How can this be done in Java?
我必须阅读一个文件,其中在每次迭代中我必须从文件中读取 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;
}
I have found this, but I think what this code is doing is completely reading a file and making a byte array of file data. But I need to ready only that many bytes that I need in one iteration.
我发现了这一点,但我认为这段代码所做的完全是读取文件并制作文件数据的字节数组。但是我只需要准备一次迭代中需要的字节数。
回答by dasblinkenlight
You can easily adapt the code to your needs: add an offset and the count, and call skip
to get past the initial N
bytes, like this -
您可以轻松地根据需要调整代码:添加偏移量和计数,然后调用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;
}
回答by McDowell
Use a DataInputfor this type of processing:
使用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
}
}
}
I've use a RandomAccessFilebut a DataInputStreamis a common alternative.
我使用了RandomAccessFile但DataInputStream是一种常见的替代方法。
回答by Philipp Seeger
Divide the code into small chunks, for example, to read a byte block (in your case 8 bytes) you need to know 3 things:
将代码分成小块,例如,要读取一个字节块(在您的情况下为 8 个字节),您需要了解 3 件事:
- In which file to read
- Where to start reading
- How many bytes to read / size of the block
- 在哪个文件中读取
- 从哪里开始阅读
- 读取多少字节/块大小
Seeing this as one step would leave you with a method that returns a byte[] array, taking the above 3 points as parameters, for example:
把这看作一个步骤会让你得到一个返回一个 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;
}
The next step would be, to open the file and call this method for every byte block in the file. You start reading the file at position zero, call that method once, do something with the result, and call it all over at position = (previousPos) + blockSize. This chunk of code could be put in another method, for example:
下一步是打开文件并为文件中的每个字节块调用此方法。您从零位置开始读取文件,调用该方法一次,对结果执行某些操作,然后在位置 = (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;
}
This returns a byte[][] array with the first index as the byteBlockNumber (first 8 bytes, second 8 bytes, third 8 bytes, ...) and the second index each individual byte:
这将返回一个 byte[][] 数组,其中第一个索引为 byteBlockNumber(前 8 个字节,第二个 8 个字节,第三个 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..
In the example code above the byte[][] array is initialized like:
在上面的示例代码中,byte[][] 数组初始化如下:
long noOfBlocks = (long) Math.ceil((double)file.length() / (double)byteBlockSize);
byte[][] result = new byte[noOfBlocks][byteBlockSize];
So the number of blocks is the number of overall bytes in the file divided by the size of the byte blocks (8 in your example). Assuming the file has 9 bytes and the block size is 8, this would result 1,sth and rounded to 1, so you won't have space for the last byte, that's why Math.ceil() is used to round up to whatever the division gives. Math.ceil(9 / 8) -> 2, and those 2 are enough to hold the first block of 8 bytes, and the last byte in a second block.
因此,块数是文件中的总字节数除以字节块的大小(在您的示例中为 8)。假设文件有 9 个字节,块大小为 8,这将导致 1,sth 并四舍五入为 1,所以最后一个字节将没有空间,这就是为什么 Math.ceil() 用于四舍五入到任何师给。Math.ceil(9 / 8) -> 2,这 2 个足以容纳第一个 8 个字节的块,以及第二个块中的最后一个字节。
回答by BullyWiiPlaza
You can use the following code to read a memory chunk with a start offset and size:
您可以使用以下代码读取具有起始偏移量和大小的内存块:
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;
}
}
Even better performance-wise, use a MappedByteBuffer
:
甚至更好的性能,使用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);
}
}
The byte array can be accessed from the ByteBuffer
using its array()
method.
可以ByteBuffer
使用它的array()
方法访问字节数组。
回答by faizan khan
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;
}