java - 在Java中将十六进制字符解码为ASCII时的奇怪行为
问题描述
我编写了一个 Java 程序来获取文件的行,并整理出一个特定的 id,然后将其从 HEX 转换为 ASCII 字符。对几个文件效果很好,直到它发现似乎是回车的“0D”十六进制字符(不知道那是做什么的)。
当它遇到这种情况时,它会结束行输出(它不应该这样做)。我无法弄清楚发生了什么。
这是代码,编译时没有错误。我附上了一张带有结果的图片。
文件 1 包含 ID=xxx:LENGHT=8 之前的字符,之后需要转换的 8 个 HEX 字符。之后,程序转换并添加同一行中的文本。我需要他们在同一条线上才能找出模式。
import java.io.*;
import java.util.Scanner;
import java.io.FileWriter;
import java.io.IOException;
public class FrameDecoder {
public static void main(String[] args) throws IOException {
try {
// Sortam frameurile cu id-ul tinta
File fisierSursa = new File("file1.txt"); //Fisierul original
FileWriter fisierData = new FileWriter("file2.txt"); //Fisierul cu frameurile care au id-ul cautat
FileWriter fisierTranzit = new FileWriter("file3.txt"); //Fisier cu caractere HEX, care va fi sters.
Scanner citireSursa = new Scanner(fisierSursa);
while (citireSursa.hasNextLine()){
String data = citireSursa.nextLine();
//System.out.println("data = " + data);
int intIndex = data.indexOf("ID=289"); // idul pe care il cauti
int intIndex2 = data.indexOf("ID=1313"); //al doilea id pe care il cauti
if (intIndex != -1 || intIndex2 != -1){
char[] text = data.toCharArray();
int counter = 0;
for (int i=0; i<text.length; i++){
if (text[i] == ':' && counter < 5){
counter++;
}
if (text[i] == ':' && counter == 5){
fisierTranzit.write(text[i+1]);
fisierTranzit.write(text[i+2]);
}
}
fisierTranzit.write("\r\n");
fisierData.write(data + "\r\n");
}
}
citireSursa.close();
fisierTranzit.close();
fisierData.close();
// Convertire HEX to ASCII
FileWriter fisierAscii = new FileWriter("file4.txt"); //Fisier care va contine caraterele ASCII decodate
File fisierTranzitRedeschis = new File("file3.txt"); //Reinitializam fisierul tranzit pentru a putea citi din el
Scanner citireTranzit = new Scanner(fisierTranzitRedeschis);
while (citireTranzit.hasNextLine()){
String data2 = citireTranzit.nextLine();
System.out.println("data2 = " + data2);
if (data2.length() % 2 != 0){
System.err.println("Invalid hex string!");
return;
}
StringBuilder builder = new StringBuilder();
for (int i=0; i<data2.length(); i=i+2){
//Impartim sirul in grupe de cate doua caractere
String s = data2.substring(i, i+2);
//Convertim fiecare grup in integer folosinf valueOfTheMetod
int n = Integer.valueOf(s, 16);
//Convertim valoare integer in char
builder.append((char)n);
}
fisierAscii.write(builder.toString() + "\r\n");
//System.out.println(builder.toString());
}
citireTranzit.close();
fisierAscii.close();
//Stergem fisierul 3
File stergereFisier3 = new File("file3.txt");
if(stergereFisier3.delete()){
System.out.println("File 3 deleted successfully");
}else{
System.out.println("Failed to delete file 3");
}
// Combinam fisierele
PrintWriter fisierFinal = new PrintWriter("file5.txt");
BufferedReader br1 = new BufferedReader(new FileReader("file2.txt"));
BufferedReader br2 = new BufferedReader(new FileReader("file4.txt"));
String line1 = br1.readLine();
String line2 = br2.readLine();
//loop to copy lines
//of file1.txt and file2.txt
//to file3.txt alternatively
while (line1 != null || line2 !=null){
if(line1 != null){
fisierFinal.print(line1 + " ");
line1 = br1.readLine();
}
if (line2 != null){
fisierFinal.println(line2 );
line2 = br2.readLine();
}
}
fisierFinal.flush();
//closing resources
br1.close();
br2.close();
fisierFinal.close();
System.out.println("Merged files succesfully");
//Stergem fisierul 2 si 4
File stergereFisier2 = new File("file2.txt");
File stergereFisier4 = new File("file4.txt");
if(stergereFisier2.delete() && stergereFisier4.delete()){
System.out.println("Files 2 and 4 deleted successfully");
}else{
System.out.println("Failed to delete files 2 and 4");
}
}catch (FileNotFoundException e){
System.out.println("An error occurred.");
e.printStackTrace();
}catch (IOException e){
System.out.println("No data to print");
e.printStackTrace();
}
}
}
编辑:我在打印 HEX 字符时作了一点小作弊,并设置了一个条件,如果遇到 0D,只需将它们替换为 00。它起作用了。我也试试你的方法,那个好像比我的好。
for (int i=0; i<text.length; i++){
if (text[i] == ':' && counter < 5){
counter++;
}
if (text[i] == ':' && counter == 5){
if(text[i+1] == '0' && text[i+2] == 'D'){
fisierTranzit.write('0');
fisierTranzit.write('0');
}
else{
fisierTranzit.write(text[i+1]);
fisierTranzit.write(text[i+2]);
}
}
}
解决方案
回车符\r
(十六进制0D
)是标准行分隔符之一,Scanner.hasNextLine()
并且nextLine()
方法假定它必须终止当前行。
要获得更多控制,请将delimiter
for Scanner 设置为仅换行符\n
并使用 hasNext/next 方法而不是 hasNextLine/nextLine 方法。例如:
Scanner citireTranzit = new Scanner(fisierTranzitRedeschis);
citireTranzit.useDelimiter("\n");
while (citireTranzit.hasNext()){
String data2 = citireTranzit.next();
...
}
推荐阅读
- webpack - 无法使用 node 12.0.0-pre 和 npm 6.6.0 OSX 安装 Webpack
- ios - 将数据从 View Controller 传递到 View
- c++ - 以数组的形式捕获屏幕的像素
- php - PHP Carbon解析错误:解析时间字符串失败
- swift - 如何在使用 Kingfisher 从 URL 加载图像后调整 UIImageView 的大小
- javascript - 限制文件输入中的文件选择数量
- python - Python循环遍历一组列表
- java - Spring OAuth2 传递状态参数
- javascript - 如何获取 Visualizer 的音轨
- javascript - 比较 2 个数组并更改属性值