经过一周的工作,我设计了二进制文件格式,并为此编写了Java阅读器。除非我使用GZip压缩功能,否则这只是一个实验,效果很好。
我称我的二进制类型为MBDF(最小二进制数据库格式),它可以存储8种不同的类型:
float
类型)double
类型)ArrayList<Object>
)String
-Object
图)我使用此数据作为测试数据:
COMPOUND {
float1: FLOAT_32 3.3
bool2: BOOLEAN true
float2: FLOAT_64 3.3
int1: INTEGER 3
compound1: COMPOUND {
xml: STRING "two length compound"
int: INTEGER 23
}
string1: STRING "Hello world!"
string2: STRING "3"
arr1: ARRAY [
STRING "Hello world!"
INTEGER 3
STRING "3"
FLOAT_32 3.29
FLOAT_64 249.2992
BOOLEAN true
COMPOUND {
str: STRING "one length compound"
}
BOOLEAN false
NULL null
]
bool1: BOOLEAN false
null1: NULL null
}
xml
复合材料的关键很重要!!
我使用以下Java代码从中获取了一个文件:
MBDFFile.writeMBDFToFile(
"/Users/<anonymous>/Documents/Java/MBDF/resources/file.mbdf",
b.makeMBDF(false)
);
在这里,变量b
是一个MBDFBinary
对象,包含上面给出的所有数据。使用此makeMBDF
功能,它会生成ISO 8859-1编码的字符串,如果给定的boolean是true
,则使用GZip压缩该字符串。然后,在写入时,在文件的开头添加了一个额外的信息字符,其中包含有关如何回读它的信息。
然后,在写完文件之后,我将其读回到java中并进行解析
MBDF mbdf = MBDFFile.readMBDFFromFile("/Users/<anonymous>/Documents/Java/MBDF/resources/file.mbdf");
System.out.println(mbdf.getBinaryObject().parse());
这将完全打印上述信息。
然后,我尝试使用压缩:
MBDFFile.writeMBDFToFile(
"/Users/<anonymous>/Documents/Java/MBDF/resources/file.mbdf",
b.makeMBDF(true)
);
与读取未压缩的文件一样,我做的读回完全一样,这应该可以工作。它打印以下信息:
COMPOUND {
float1: FLOAT_32 3.3
bool2: BOOLEAN true
float2: FLOAT_64 3.3
int1: INTEGER 3
compound1: COMPOUND {
xUT: STRING 'two length compound'
int: INTEGER 23
}
string1: STRING 'Hello world!'
string2: STRING '3'
arr1: ARRAY [
STRING 'Hello world!'
INTEGER 3
STRING '3'
FLOAT_32 3.29
FLOAT_64 249.2992
BOOLEAN true
COMPOUND {
str: STRING 'one length compound'
}
BOOLEAN false
NULL null
]
bool1: BOOLEAN false
null1: NULL null
}
将其与初始信息进行比较,由于某种原因,名称xml
更改为xUT
...
经过一些研究,我发现压缩前和压缩后的二进制数据几乎没有差异。这样的模式110011
变成了101010
。
当我将名称xml
加长时,例如xmldm
,由于xmldm
某种原因,它只是被解析了。我目前看到的问题仅出现在三个字符的名称上。
直接压缩和解压缩生成的字符串(无需将其保存到文件中并读取该字符串)确实可行,因此,该错误可能是由文件编码引起的。
据我所知,字符串输出为ISO 8859-1格式,但是我无法正确获得文件编码。读取文件时,将按必须读取的文件进行读取,并且所有字符均读取为ISO 8859-1字符。
我有些事情可能是原因,我实际上不知道如何测试它们:
但是哪一个是正确的,如果没有一个是正确的,那么导致此错误的真正原因是什么?
我现在无法弄清楚。
MBDFFile类,读取和存储文件:
/* MBDFFile.java */
package com.redgalaxy.mbdf;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class MBDFFile {
public static MBDF readMBDFFromFile(String filename) throws IOException {
// FileInputStream is = new FileInputStream(filename);
// InputStreamReader isr = new InputStreamReader(is, "ISO-8859-1");
// BufferedReader br = new BufferedReader(isr);
//
// StringBuilder builder = new StringBuilder();
//
// String currentLine;
//
// while ((currentLine = br.readLine()) != null) {
// builder.append(currentLine);
// builder.append("\n");
// }
//
// builder.deleteCharAt(builder.length() - 1);
//
//
// br.close();
Path path = Paths.get(filename);
byte[] data = Files.readAllBytes(path);
return new MBDF(new String(data, "ISO-8859-1"));
}
private static void writeToFile(String filename, byte[] txt) throws IOException {
// BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
//// FileWriter writer = new FileWriter(filename);
// writer.write(txt.getBytes("ISO-8859-1"));
// writer.close();
// PrintWriter pw = new PrintWriter(filename, "ISO-8859-1");
FileOutputStream stream = new FileOutputStream(filename);
stream.write(txt);
stream.close();
}
public static void writeMBDFToFile(String filename, MBDF info) throws IOException {
writeToFile(filename, info.pack().getBytes("ISO-8859-1"));
}
}
该pack
函数以ISO 8859-1格式生成文件的最终字符串。
有关所有其他代码,请参见我的MBDF Github存储库。
我评论了我尝试过的代码,试图展示我尝试过的内容。
我的工作区:-Macbook Air '11(High Sierra)-IntellIJ社区2017.3-JDK 1.8
我希望这是足够的信息,这实际上是弄清楚我在做什么以及到底在做什么的唯一方法。
MBDF.java
/* MBDF.java */
package com.redgalaxy.mbdf;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class MBDF {
private String data;
private InfoTag tag;
public MBDF(String data) {
this.tag = new InfoTag((byte) data.charAt(0));
this.data = data.substring(1);
}
public MBDF(String data, InfoTag tag) {
this.tag = tag;
this.data = data;
}
public MBDFBinary getBinaryObject() throws IOException {
String uncompressed = data;
if (tag.isCompressed) {
uncompressed = GZipUtils.decompress(data);
}
Binary binary = getBinaryFrom8Bit(uncompressed);
return new MBDFBinary(binary.subBit(0, binary.getLen() - tag.trailing));
}
public static Binary getBinaryFrom8Bit(String s8bit) {
try {
byte[] bytes = s8bit.getBytes("ISO-8859-1");
return new Binary(bytes, bytes.length * 8);
} catch( UnsupportedEncodingException ignored ) {
// This is not gonna happen because encoding 'ISO-8859-1' is always supported.
return new Binary(new byte[0], 0);
}
}
public static String get8BitFromBinary(Binary binary) {
try {
return new String(binary.getByteArray(), "ISO-8859-1");
} catch( UnsupportedEncodingException ignored ) {
// This is not gonna happen because encoding 'ISO-8859-1' is always supported.
return "";
}
}
/*
* Adds leading zeroes to the binary string, so that the final amount of bits is 16
*/
private static String addLeadingZeroes(String bin, boolean is16) {
int len = bin.length();
long amount = (long) (is16 ? 16 : 8) - len;
// Create zeroes and append binary string
StringBuilder zeroes = new StringBuilder();
for( int i = 0; i < amount; i ++ ) {
zeroes.append(0);
}
zeroes.append(bin);
return zeroes.toString();
}
public String pack(){
return tag.getFilePrefixChar() + data;
}
public String getData() {
return data;
}
public InfoTag getTag() {
return tag;
}
}
此类包含pack()
方法。data
已在此处压缩(如果应该压缩)。
对于其他课程,请观看Github存储库,我不想让我的问题太久。
自己解决!
好像是读写系统。导出文件时,我使用ISO-8859-1表创建了一个字符串,以将字节转换为字符。我将该字符串写入了一个文本文件,即UTF-8。最大的问题是我使用FileWriter
实例编写了文本文件的实例。
阅读使用逆系统。整个文件作为字符串读入内存(消耗内存!),然后被解码。
我不知道文件是二进制数据,它们的特定格式形成文本数据。ISO-8859-1和UTF-8是其中一些格式。我在使用UTF-8时遇到问题,因为它将一些字符分成了两个字节,我无法管理...
我的解决方案是使用流。Java中存在FileInputStream
s和FileOutputStream
s,可用于读写二进制文件。我没有使用流,因为我认为并没有太大的区别(“文件是文本,所以有什么问题吗?”),但是有...我实现了这一点(通过编写一个新的类似库),我m现在能够将每个输入流传递给解码器,并将每个输出流传递给编码器。要制作未压缩的文件,您需要传递FileOutputStream
。GZipped文件可以GZipOutputStream
依靠来使用FileOutputStream
。如果有人想要带有二进制数据的字符串,则ByteArrayOutputStream
可以使用a。相同的规则适用于阅读,其中InputStream
应使用提到的流的变体。
不再存在UTF-8或ISO-8859-1问题,即使使用GZip,它也似乎可以工作!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句