我正在尝试将二进制文件(如视频/音频/图像)分成每个100kb的块,然后将这些块连接起来以取回原始文件。 我的代码似乎正在工作,在它分割文件并加入块的意义上,我得到的文件与原始文件大小相同。然而,问题是内容被截断 - 也就是说,如果它是一个视频文件,它会在2秒后停止,如果它是图像文件,那么只有上半部分看起来正确。
以下是我正在使用的代码(如果您愿意,我可以发布整个代码):
分割:
File ifile = new File(fname);
FileInputStream fis;
String newName;
FileOutputStream chunk;
int fileSize = (int) ifile.length();
int nChunks = 0, read = 0, readLength = Chunk_Size;
byte[] byteChunk;
try {
fis = new FileInputStream(ifile);
StupidTest.size = (int)ifile.length();
while (fileSize > 0) {
if (fileSize <= Chunk_Size) {
readLength = fileSize;
}
byteChunk = new byte[readLength];
read = fis.read(byteChunk, 0, readLength);
fileSize -= read;
assert(read==byteChunk.length);
nChunks++;
newName = fname + ".part" + Integer.toString(nChunks - 1);
chunk = new FileOutputStream(new File(newName));
chunk.write(byteChunk);
chunk.flush();
chunk.close();
byteChunk = null;
chunk = null;
}
fis.close();
fis = null;
为了加入文件,我将所有块的名称放在List中,然后按名称对其进行排序,然后运行以下代码:
File ofile = new File(fname);
FileOutputStream fos;
FileInputStream fis;
byte[] fileBytes;
int bytesRead = 0;
try {
fos = new FileOutputStream(ofile,true);
for (File file : files) {
fis = new FileInputStream(file);
fileBytes = new byte[(int) file.length()];
bytesRead = fis.read(fileBytes, 0,(int) file.length());
assert(bytesRead == fileBytes.length);
assert(bytesRead == (int) file.length());
fos.write(fileBytes);
fos.flush();
fileBytes = null;
fis.close();
fis = null;
}
fos.close();
fos = null;
答案 0 :(得分:10)
我只能在代码中发现2个潜在的错误:
int fileSize = (int) ifile.length();
当文件超过2GB时,上述操作失败,因为int
无法容纳更多文件。
newName = fname + ".part" + Integer.toString(nChunks - 1);
这样构造的文件名应该以非常具体的方式排序。使用默认字符串排序时,name.part10
将在name.part2
之前出现。您想提供一个自定义Comparator
,它将部件号提取并解析为int,然后进行比较。
答案 1 :(得分:3)
为了加入文件,我将所有块的名称放在List中,然后按名称对其进行排序,然后运行以下代码:
但你的名字是以下形式:
newName = fname + ".part" + Integer.toString(nChunks - 1);
仔细考虑如果您有11个或更多部件会发生什么。哪个字符串按字母顺序排在第一位:“。part10”或“.part2”? (答案:“。part10”,因为'1'在字符编码中位于'2'之前。)
答案 2 :(得分:1)
是否有超过10个块?然后程序将连接* .part1 + * .part10 + * .part2,依此类推。
答案 3 :(得分:1)
分割文件:-----&gt;
import java.io.*;
class Split
{
public static void main(String args[])throws IOException
{
Console con=System.console();
System.out.println("enter the file name");
String path=con.readLine();
File f= new File(path);
int filesize=(int)f.length();
FileInputStream fis= new FileInputStream(path);
int size;
System.out.println("enter file size for split");
size=Integer.parseInt(con.readLine());
byte b[]=new byte[size];
int ch,c=0;
while(filesize>0)
{
ch=fis.read(b,0,size);
filesize = filesize-ch;
String fname=c+"."+f.getName()+"";
c++;
FileOutputStream fos= new FileOutputStream(new File(fname));
fos.write(b,0,ch);
fos.flush();
fos.close();
}
fis.close();
}
}
答案 4 :(得分:1)
public class FileSplitter {
private static final int BUFSIZE = 4*1024;
public boolean needsSplitting(String file, int chunkSize) {
return new File(file).length() > chunkSize;
}
private static boolean isASplitFileChunk(String file) {
return chunkIndexLen(file) > 0;
}
private static int chunkIndexLen(String file) {
int n = numberOfTrailingDigits(file);
if (n > 0) {
String zeroes = new String(new char[n]).replace("\0", "0");
if (file.matches(".*\\.part[0-9]{"+n+"}?of[0-9]{"+n+"}?$") && !file.endsWith(zeroes) && !chunkNumberStr(file, n).equals(zeroes)) {
return n;
}
}
return 0;
}
private static String getWholeFileName(String chunkName) {
int n = chunkIndexLen(chunkName);
if (n>0) {
return chunkName.substring(0, chunkName.length() - 7 - 2*n); // 7+2n: 1+4+n+2+n : .part012of345
}
return chunkName;
}
private static int getNumberOfChunks(String filename) {
int n = chunkIndexLen(filename);
if (n > 0) {
try {
String digits = chunksTotalStr(filename, n);
return Integer.parseInt(digits);
} catch (NumberFormatException x) { // should never happen
}
}
return 1;
}
private static int getChunkNumber(String filename) {
int n = chunkIndexLen(filename);
if (n > 0) {
try {
// filename.part001of200
String digits = chunkNumberStr(filename, n);
return Integer.parseInt(digits)-1;
} catch (NumberFormatException x) {
}
}
return 0;
}
private static int numberOfTrailingDigits(String s) {
int n=0, l=s.length()-1;
while (l>=0 && Character.isDigit(s.charAt(l))) {
n++; l--;
}
return n;
}
private static String chunksTotalStr(String filename, int chunkIndexLen) {
return filename.substring(filename.length()-chunkIndexLen);
}
protected static String chunkNumberStr(String filename, int chunkIndexLen) {
int p = filename.length() - 2 - 2*chunkIndexLen; // 123of456
return filename.substring(p,p+chunkIndexLen);
}
// 0,8 ==> part1of8; 7,8 ==> part8of8
private static String chunkFileName(String filename, int n, int total, int chunkIndexLength) {
return filename+String.format(".part%0"+chunkIndexLength+"dof%0"+chunkIndexLength+"d", n+1, total);
}
public static String[] splitFile(String fname, long chunkSize) throws IOException {
FileInputStream fis = null;
ArrayList<String> res = new ArrayList<String>();
byte[] buffer = new byte[BUFSIZE];
try {
long totalSize = new File(fname).length();
int nChunks = (int) ((totalSize + chunkSize - 1) / chunkSize);
int chunkIndexLength = String.format("%d", nChunks).length();
fis = new FileInputStream(fname);
long written = 0;
for (int i=0; written<totalSize; i++) {
String chunkFName = chunkFileName(fname, i, nChunks, chunkIndexLength);
FileOutputStream fos = new FileOutputStream(chunkFName);
try {
written += copyStream(fis, buffer, fos, chunkSize);
} finally {
Closer.closeSilently(fos);
}
res.add(chunkFName);
}
} finally {
Closer.closeSilently(fis);
}
return res.toArray(new String[0]);
}
public static boolean canJoinFile(String chunkName) {
int n = chunkIndexLen(chunkName);
if (n>0) {
int nChunks = getNumberOfChunks(chunkName);
String filename = getWholeFileName(chunkName);
for (int i=0; i<nChunks; i++) {
if (!new File(chunkFileName(filename, i, nChunks, n)).exists()) {
return false;
}
}
return true;
}
return false;
}
public static void joinChunks(String chunkName) throws IOException {
int n = chunkIndexLen(chunkName);
if (n>0) {
int nChunks = getNumberOfChunks(chunkName);
String filename = getWholeFileName(chunkName);
byte[] buffer = new byte[BUFSIZE];
FileOutputStream fos = new FileOutputStream(filename);
try {
for (int i=0; i<nChunks; i++) {
FileInputStream fis = new FileInputStream(chunkFileName(filename, i, nChunks, n));
try {
copyStream(fis, buffer, fos, -1);
} finally {
Closer.closeSilently(fis);
}
}
} finally {
Closer.closeSilently(fos);
}
}
}
public static boolean deleteAllChunks(String chunkName) {
boolean res = true;
int n = chunkIndexLen(chunkName);
if (n>0) {
int nChunks = getNumberOfChunks(chunkName);
String filename = getWholeFileName(chunkName);
for (int i=0; i<nChunks; i++) {
File f = new File(chunkFileName(filename, i, nChunks, n));
res &= (f.delete() || !f.exists());
}
}
return res;
}
private static long copyStream(FileInputStream fis, byte[] buffer, FileOutputStream fos, long maxAmount) throws IOException {
long chunkSizeWritten;
for (chunkSizeWritten=0; chunkSizeWritten<maxAmount || maxAmount<0; ) {
int toRead = maxAmount < 0 ? buffer.length : (int)Math.min(buffer.length, maxAmount - chunkSizeWritten);
int lengthRead = fis.read(buffer, 0, toRead);
if (lengthRead < 0) {
break;
}
fos.write(buffer, 0, lengthRead);
chunkSizeWritten += lengthRead;
}
return chunkSizeWritten;
}
}
借用Closer
here或from org.apache.logging.log4j.core.util。
答案 5 :(得分:0)
对文件进行二进制比较时会发生什么。例如与差异。你看到第一个文件后有什么区别吗?
您可以尝试分解文本TXT文件吗?如果有字节不合适,那么出错的原因应该更明显。例如重复的块/文件/或充满nul字节的数据。 ??
编辑:正如其他人注意到的那样,您没有按特定顺序阅读文件。你可以做的是使用填充文件号,如。newName = String.format("%s.part%09d", fname, nChunks - 1);
这将按数字顺序为您提供最多10亿个文件。
当您阅读文件时,您需要确保它们已排序。
Arrays.sort(files);
for (File file : files) {
使用其他人建议的自定义比较器会减少填充数字的大小,但能够按名称排序以获得正确的顺序可能会很好。例如在探险家。
答案 6 :(得分:0)
需要拆分文件名和目标文件大小(以字节为单位)形成用户并将其拆分为子文件,它适用于所有类型的文件,如(.bin,.jpg,.rar)
import java.io.*;
class split{
public static void main(String args[])throws IOException {
String a;
int b;
long len;
Console con=System.console();
System.out.println("Enter File Name: ");
File f=new File(con.readLine());
System.out.println("Enter Destination File Size: ");
b=Integer.parseInt(con.readLine());
FileInputStream fis=new FileInputStream(f);
len=f.length();
int c=(int)len/b;
if(((int)len%b)!=0)
c++;
for(int i=0;i<c;i++){
File f1=new File(i+""+"."+f);
FileOutputStream fos=new FileOutputStream(f1);
for(int j=0;j<b;j++){
int ch;
if((ch=fis.read())!=-1)
fos.write(ch); } }
fis.close();
System.out.println("Operation Successful"); }}
和另一个程序将合并所有拆分文件。它只采用拆分文件名并合并所有文件。
import java.io.*;
class merge{
static int i;
public static void main(String args[])throws IOException{
String a;
int b;
long len;
Console con=System.console();
System.out.println("Enter File to be retrived: ");
File f=new File(con.readLine());
FileOutputStream fos=new FileOutputStream(f,true);
try {
File f1=new File(i+""+"."+f);
while((f1.exists())!=false) {
int ch;
FileInputStream fis=new FileInputStream(i+""+"."+f);
i++;
while((ch=fis.read())!=-1){
fos.write(ch); }}}
catch(FileNotFoundException e1){} }}