Java 中的文件拆分代码未按要求工作
File Splitting code in Java is not working as required
我试过下面的文件拆分代码,它可以工作,但不符合要求。
即一个 mp3 文件名 'song.mp3' 的大小为 2540KB,预期的块数(每个 100KB)为 25,但代码只给出了 12 个块,我不明白原因。
public static void main(String[] args) throws IOException {
File file = new File("song.mp3");
FileInputStream fIn = new FileInputStream("song.mp3");
FileOutputStream fOut = new FileOutputStream("song_0.mp3");
int chunk_size = 1024 * 100;
byte[] buff = new byte[chunk_size]; // 100KB file
int i = 0;
String file_name = file.getName();
String file_name_base = file_name.substring(0,
file_name.lastIndexOf("."));
while (fIn.read() != -1) {
fIn.read(buff);
int total_read = 0;
total_read += chunk_size;
long read_next_chunk = total_read;
String file_name_new = file_name_base + "_" + i + ".mp3";
File file_new = new File(file_name_base);
i++;
fOut = new FileOutputStream(file_name_new);
fOut.write(buff);
fIn.skip(total_read);// skip the total read part
} // end of while loop
fIn.close();
fOut.close();
}
你的代码肯定行不通,至少是因为:
在每次迭代中,您读取 1 个字节并将其丢弃 while (fIn.read() != -1)
.
将循环更改为如下内容:
int bytesReadCounter;
while((bytesReadCounter = fIn.read(buff, 0, chunk_size)) > 0){
..................................
fOut.write(buff, 0, bytesReadCounter);
..................................
}
在 buff
中存储读取的字节数,在 bytesReadCounter
中存储读取的字节数。
然后,您从 buff
正好 bytesReadCounter
字节写入 fOut
。
编辑,使用此代码:
public static void main(String[] args) {
File file = new File("song.mp3");
FileInputStream fIn = null;
try {
fIn = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int chunk_size = 1024 * 100;
byte[] buff = new byte[chunk_size]; // 100KB file
int i = 0;
String file_name = file.getName();
String file_name_base = file_name.substring(0, file_name.lastIndexOf("."));
int bytesReadCounter;
boolean hasMore = true;
while (hasMore) {
try {
bytesReadCounter = fIn.read(buff, 0, chunk_size);
} catch (IOException e) {
e.printStackTrace();
break;
}
hasMore = bytesReadCounter > 0;
if (!hasMore)
break;
String file_name_new = file_name_base + "_" + i + ".mp3";
File file_new = new File(file_name_new);
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(file_new);
} catch (FileNotFoundException e) {
e.printStackTrace();
break;
}
try {
fOut.write(buff, 0, bytesReadCounter);
fOut.close();
} catch (IOException e) {
e.printStackTrace();
break;
}
i++;
}
try {
fIn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
我想立即推荐更新的 Path/Files
类.
以下代码未经测试,但有清晰的缓冲读数:
- 顺序读取原文件
- 循环零件
- 使用缓冲区 (
block
) 写入一部分 - 这比单纯的 FileInputStream 更快
所以:
public static void splitFile(String file) throws IOException {
final long partSize = 100 * 1024;
Path originalPath = Paths.get(file);
if (Files.isReadable(originalPath)) {
throw new FileNotFoundException("Is not a readable file: " + originalPath);
}
// Read the file:
long totalSizeToRead = Files.size(originalPath);
try (InputStream in = Files.newInputStream(originalPath)) {
int partNo = 0;
byte[] block = new byte[16 * 1024];
// Write parts
while (totalSizeToRead > 0) {
// Write part
++partNo;
Path partPath = Paths.get(String.format("%s-%03d.part", file, partNo));
int sizeToReadInPart = partSize;
if (totalSizeToRead < sizeToReadInPart) {
sizeToReadInPart = (int) totalSizeToRead;
}
try (OutputStream out = Files.newOutputStream(partPath,
StandardOpenOptions.REPLACE_EXISTING)) {
// Write blocks of part
while (sizeToReadInPart > 0) {
int toRead = Math.min(block.length, sizeToReadInPart);
int actuallyRead = in.read(block, 0, toRead);
sizeToReadInPart -= actuallyRead;
if (actuallyRead <= 0) {
break;
}
out.write(block, 0, actuallyRead);
}
}
totalSizeToRead -= sizeToReadInPart;
}
}
}
这里的要点:
- try-with-resource 自动关闭,即使出现 return/break/thrown 异常。
- 我使用文件大小 (a Long) 和 int 作为缓冲区大小,需要注意一下。这也是一个冗余,给定
actuallyRead
.
- Java 按照惯例,对普通变量使用驼峰式而不是下划线。
我试过下面的文件拆分代码,它可以工作,但不符合要求。 即一个 mp3 文件名 'song.mp3' 的大小为 2540KB,预期的块数(每个 100KB)为 25,但代码只给出了 12 个块,我不明白原因。
public static void main(String[] args) throws IOException {
File file = new File("song.mp3");
FileInputStream fIn = new FileInputStream("song.mp3");
FileOutputStream fOut = new FileOutputStream("song_0.mp3");
int chunk_size = 1024 * 100;
byte[] buff = new byte[chunk_size]; // 100KB file
int i = 0;
String file_name = file.getName();
String file_name_base = file_name.substring(0,
file_name.lastIndexOf("."));
while (fIn.read() != -1) {
fIn.read(buff);
int total_read = 0;
total_read += chunk_size;
long read_next_chunk = total_read;
String file_name_new = file_name_base + "_" + i + ".mp3";
File file_new = new File(file_name_base);
i++;
fOut = new FileOutputStream(file_name_new);
fOut.write(buff);
fIn.skip(total_read);// skip the total read part
} // end of while loop
fIn.close();
fOut.close();
}
你的代码肯定行不通,至少是因为:
在每次迭代中,您读取 1 个字节并将其丢弃 while (fIn.read() != -1)
.
将循环更改为如下内容:
int bytesReadCounter;
while((bytesReadCounter = fIn.read(buff, 0, chunk_size)) > 0){
..................................
fOut.write(buff, 0, bytesReadCounter);
..................................
}
在 buff
中存储读取的字节数,在 bytesReadCounter
中存储读取的字节数。
然后,您从 buff
正好 bytesReadCounter
字节写入 fOut
。
编辑,使用此代码:
public static void main(String[] args) {
File file = new File("song.mp3");
FileInputStream fIn = null;
try {
fIn = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int chunk_size = 1024 * 100;
byte[] buff = new byte[chunk_size]; // 100KB file
int i = 0;
String file_name = file.getName();
String file_name_base = file_name.substring(0, file_name.lastIndexOf("."));
int bytesReadCounter;
boolean hasMore = true;
while (hasMore) {
try {
bytesReadCounter = fIn.read(buff, 0, chunk_size);
} catch (IOException e) {
e.printStackTrace();
break;
}
hasMore = bytesReadCounter > 0;
if (!hasMore)
break;
String file_name_new = file_name_base + "_" + i + ".mp3";
File file_new = new File(file_name_new);
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(file_new);
} catch (FileNotFoundException e) {
e.printStackTrace();
break;
}
try {
fOut.write(buff, 0, bytesReadCounter);
fOut.close();
} catch (IOException e) {
e.printStackTrace();
break;
}
i++;
}
try {
fIn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
我想立即推荐更新的 Path/Files
类.
以下代码未经测试,但有清晰的缓冲读数:
- 顺序读取原文件
- 循环零件
- 使用缓冲区 (
block
) 写入一部分 - 这比单纯的 FileInputStream 更快
所以:
public static void splitFile(String file) throws IOException {
final long partSize = 100 * 1024;
Path originalPath = Paths.get(file);
if (Files.isReadable(originalPath)) {
throw new FileNotFoundException("Is not a readable file: " + originalPath);
}
// Read the file:
long totalSizeToRead = Files.size(originalPath);
try (InputStream in = Files.newInputStream(originalPath)) {
int partNo = 0;
byte[] block = new byte[16 * 1024];
// Write parts
while (totalSizeToRead > 0) {
// Write part
++partNo;
Path partPath = Paths.get(String.format("%s-%03d.part", file, partNo));
int sizeToReadInPart = partSize;
if (totalSizeToRead < sizeToReadInPart) {
sizeToReadInPart = (int) totalSizeToRead;
}
try (OutputStream out = Files.newOutputStream(partPath,
StandardOpenOptions.REPLACE_EXISTING)) {
// Write blocks of part
while (sizeToReadInPart > 0) {
int toRead = Math.min(block.length, sizeToReadInPart);
int actuallyRead = in.read(block, 0, toRead);
sizeToReadInPart -= actuallyRead;
if (actuallyRead <= 0) {
break;
}
out.write(block, 0, actuallyRead);
}
}
totalSizeToRead -= sizeToReadInPart;
}
}
}
这里的要点:
- try-with-resource 自动关闭,即使出现 return/break/thrown 异常。
- 我使用文件大小 (a Long) 和 int 作为缓冲区大小,需要注意一下。这也是一个冗余,给定
actuallyRead
. - Java 按照惯例,对普通变量使用驼峰式而不是下划线。