与 C# 相比,从 Java 获取错误字节
Getting wrong bytes from Java compared to C#
所以我有一些 FRX 二进制文件,我试图使用 Java 的二进制读取方法从中获取字符串标题。
我能够这样做,并使用以下程序在 C# 中指定读取字节的区域:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
public class GetFromFRX
{
public static void Main()
{
StringBuilder buffer = new StringBuilder();
using (BinaryReader b = new BinaryReader(File.Open("frmResidency.frx", FileMode.Open)))
{
try
{
b.BaseStream.Seek(641, SeekOrigin.Begin);
int length = b.ReadInt32();
for (int i = 0; i < length; i++)
{
buffer.Append(b.ReadChar());
}
}
catch (Exception e)
{
Console.WriteLine( "Error obtaining resource\n" + e.Message);
}
}
Console.WriteLine(buffer);
}
}
问题更新:
尝试在 Java 中做同样的事情,我构建了以下程序。现在我已经实现了 Guava 以使用 LittleEndian
等价物,但是现在我的长度打印 24,结果我只得到输出文件中的前 24 个字节。 ReadInt
是否不适合这种情况,其功能与 ReadInt32
不同?
import java.io.*;
import com.google.common.io.*;
public class RealJavaByteReader {
public static void main(String[] args) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("frmResidency.frx");
LittleEndianDataInputStream din = new LittleEndianDataInputStream(in);
out = new FileOutputStream("output.txt");
int length = din.readInt();
System.out.println(length);
int c;
for (c = 0; c < length; c++) {
// TODO: first read byte and check for EOF
out.write(din.read());
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
Elizion,
这可能是因为您可能正在读取使用小端存储的 int。因此,Java 使用 Big endian 和 .NET little endian。
使用如下函数将java中的little endian int转换为big endian int。
/**
* Byte swap a single int value.
*
* @param value Value to byte swap.
* @return Byte swapped representation.
*/
public static int swap (int value)
{
int b1 = (value >> 0) & 0xff;
int b2 = (value >> 8) & 0xff;
int b3 = (value >> 16) & 0xff;
int b4 = (value >> 24) & 0xff;
return b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0;
}
请尝试查看以下post。
Converting Little Endian to Big Endian
此时我意识到我的错误所在。现在 LittleEndianDataInputStream
已经实现,我可以正确地使用 SkipBytes
来设置我的初始字节位置,并根据需要 return 字符串标题。当然,我最初只会生成前 24 个字节,因为对于 FRX 文件中的某些给定 属性,二进制文件的前 4 个字节中的任何内容的长度都必须为 24。我必须使用 skipBytes
设置偏移量才能生成任何有意义的内容,因为 FRX 文件中的属性长度以 4 个字节为一组存储,后面跟着包含 属性 的那些字节。
例如,如果我设置 din.skipBytes(308);
,那么 FRX 文件中的第 308 到第 312 个字节包含我需要的标题 属性 中字符串的 byte-length(例如140),由readInt
输出。因此接下来的 140 个字节将包含我需要的字符串,并且我的 for
循环将正确迭代。
所以我有一些 FRX 二进制文件,我试图使用 Java 的二进制读取方法从中获取字符串标题。
我能够这样做,并使用以下程序在 C# 中指定读取字节的区域:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
public class GetFromFRX
{
public static void Main()
{
StringBuilder buffer = new StringBuilder();
using (BinaryReader b = new BinaryReader(File.Open("frmResidency.frx", FileMode.Open)))
{
try
{
b.BaseStream.Seek(641, SeekOrigin.Begin);
int length = b.ReadInt32();
for (int i = 0; i < length; i++)
{
buffer.Append(b.ReadChar());
}
}
catch (Exception e)
{
Console.WriteLine( "Error obtaining resource\n" + e.Message);
}
}
Console.WriteLine(buffer);
}
}
问题更新:
尝试在 Java 中做同样的事情,我构建了以下程序。现在我已经实现了 Guava 以使用 LittleEndian
等价物,但是现在我的长度打印 24,结果我只得到输出文件中的前 24 个字节。 ReadInt
是否不适合这种情况,其功能与 ReadInt32
不同?
import java.io.*;
import com.google.common.io.*;
public class RealJavaByteReader {
public static void main(String[] args) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("frmResidency.frx");
LittleEndianDataInputStream din = new LittleEndianDataInputStream(in);
out = new FileOutputStream("output.txt");
int length = din.readInt();
System.out.println(length);
int c;
for (c = 0; c < length; c++) {
// TODO: first read byte and check for EOF
out.write(din.read());
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
Elizion,
这可能是因为您可能正在读取使用小端存储的 int。因此,Java 使用 Big endian 和 .NET little endian。
使用如下函数将java中的little endian int转换为big endian int。
/**
* Byte swap a single int value.
*
* @param value Value to byte swap.
* @return Byte swapped representation.
*/
public static int swap (int value)
{
int b1 = (value >> 0) & 0xff;
int b2 = (value >> 8) & 0xff;
int b3 = (value >> 16) & 0xff;
int b4 = (value >> 24) & 0xff;
return b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0;
}
请尝试查看以下post。
Converting Little Endian to Big Endian
此时我意识到我的错误所在。现在 LittleEndianDataInputStream
已经实现,我可以正确地使用 SkipBytes
来设置我的初始字节位置,并根据需要 return 字符串标题。当然,我最初只会生成前 24 个字节,因为对于 FRX 文件中的某些给定 属性,二进制文件的前 4 个字节中的任何内容的长度都必须为 24。我必须使用 skipBytes
设置偏移量才能生成任何有意义的内容,因为 FRX 文件中的属性长度以 4 个字节为一组存储,后面跟着包含 属性 的那些字节。
例如,如果我设置 din.skipBytes(308);
,那么 FRX 文件中的第 308 到第 312 个字节包含我需要的标题 属性 中字符串的 byte-length(例如140),由readInt
输出。因此接下来的 140 个字节将包含我需要的字符串,并且我的 for
循环将正确迭代。