我有一个二进制文件,已上传到云存储。我必须将该文件写入输出流。然后当我想下载文件时,我需要从InputStream中读取它的内容。但是我没有得到相同的文件。以下是完整的工作代码,但存在该错误。排除云和其他代码,因为问题不存在。
我已经阅读了 Java 文档来构造从流的读取和写入,但我找不到问题所在 - 为什么在写入输出流然后从输入流读取后我得到不同的数据。任何建议将不胜感激!
public class TActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create any binary file, e.g., a DB file
String dbName = "bed872bc-bc8f-4429-8126-070a48c13bdf"; // Just a random UUID
try (SQLiteDatabase db = openOrCreateDatabase(dbName, Context.MODE_PRIVATE, null)) { ; };
try {
// Write the binary file into Output stream
File originalFile = getDatabasePath(dbName);
long originalFileLength = originalFile.length();
ByteArrayOutputStream memoryStreamOut = new ByteArrayOutputStream();
WriteFromFile(memoryStreamOut, originalFile.toString());
// Write from the memory stream into the file - expected result is that we end up with identical file content as the original file
ByteArrayInputStream memoryStreamIn = new ByteArrayInputStream(memoryStreamOut.toByteArray());
File againTheSameFile = CreateTemporaryFileSafe(this);
WriteToFile(memoryStreamIn, againTheSameFile);
// Check whether the files have same size - they should have because they should be identical
long newFileLength = againTheSameFile.length();
if (newFileLength != originalFileLength) {
// it ends up here - they don't equal!
}
}
catch (Exception E) {
// Log ...
}
}
public static void WriteFromFile(OutputStream outputStream, String filePath) throws Exception {
try (Writer writer = new OutputStreamWriter(outputStream)) {
try (FileInputStream fileinputstream = new FileInputStream(filePath)) {
byte[] buffer = new byte[64 * 1024];
int length;
while ((length = fileinputstream.read(buffer)) != -1) {
writer.write(new String(buffer, 0, length));
}
}
}
}
public static void WriteToFile(InputStream inputStream, File file) throws Exception {
try (DataInputStream reader = new DataInputStream(inputStream)) {
try (DataOutputStream fileOutputStream = new DataOutputStream(new FileOutputStream(file))) {
byte[] buffer = new byte[64 * 1024];
int length;
while ((length = reader.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, length);
}
}
}
}
public static File CreateTemporaryFileSafe(Context context) {
try { return File.createTempFile(UUID.randomUUID().toString(), "tmp", context.getCacheDir()); }
catch (IOException E) { return null; }
}
}
最佳答案
简短的回答:您的二进制数据因从字节到字符串然后是字符串到字节的(不必要的)转换而被损坏。相反,只需将其读取为字节,然后将其写入为字节:
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
class Foo {
private static void copyStream(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[64*1024];
int length;
while ((length = input.read(buffer)) != -1) {
output.write(buffer,0,length);
}
}
private static void copyFile(String inputPath, String outputPath) throws IOException {
try (
FileInputStream input = new FileInputStream(inputPath);
FileOutputStream output = new FileOutputStream(outputPath)
) {
copyStream(input, output);
}
}
public static void main(String[] args) throws IOException {
copyFile(args[0], args[1]);
}
}
更长的答案是,当您使用 String(bytes,0,len) 将字节转换为字符串时,java 将使用 JVM 的默认字符集(可能是 UTF-8)进行该转换。但您的文件不是 UTF-8 编码文本,而是随机字节。其中许多字节都不是正确的 UTF-8。 Java 会默默地用 unicode 'REPLACMENT CHARACTER' 替换每个非法字节,即\uFFFD。
然后,当您将其写回时,您使用了 OutputStreamWriter(OutputStream),它使用默认字符集将(已损坏的)数据转换回字节。假设默认编码为 UTF-8,则替换字符的每个实例都会替换为该字符的 UTF-8 编码,即字节 0xef 0xbf 0xbd。 IE。将其变成三个字节。这就是文件大小发生变化的原因:输入文件中不符合合法 UTF-8 的每个字节都会在输出文件中更改为三个字节。
关于java - 将二进制文件保存到 OutputStream 并返回到 InputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48599081/