Java 从字节数组中提取字符串的第一个有效行

Java 从字节数组中提取字符串的第一个有效行,java,unicode,Java,Unicode,我正在用Java编写一个实用程序,用于读取可能包含文本和二进制数据的流。我希望避免I/O等待。为此,我创建了一个线程,以保持读取数据并等待数据进入缓冲区,这样客户机就可以检查可用性,并随时通过关闭输入流来终止等待,这将生成IOException并停止等待。就从中读取字节而言,这种方法非常有效;就二进制而言 现在,我还想让客户端能够轻松地从中读取行,如“.hasNextLine”和“.readLine”。如果不使用I/O等待流(如缓冲流),Q1如何检查二进制字节[]是否包含第一行长度形式的有效un

我正在用Java编写一个实用程序,用于读取可能包含文本和二进制数据的流。我希望避免I/O等待。为此,我创建了一个线程,以保持读取数据并等待数据进入缓冲区,这样客户机就可以检查可用性,并随时通过关闭输入流来终止等待,这将生成IOException并停止等待。就从中读取字节而言,这种方法非常有效;就二进制而言

现在,我还想让客户端能够轻松地从中读取行,如“.hasNextLine”和“.readLine”。如果不使用I/O等待流(如缓冲流),Q1如何检查二进制字节[]是否包含第一行长度形式的有效unicode行?我查看了字符串/字符集API,但找不到它,或者找不到它?。注意:如果可能,我不想使用非内置库

因为我找不到一个,所以我尝试创建一个。没有这么复杂,这是我的算法

一,。我从字节数组的开头开始查找,直到找到“\n”或没有“\n”的“\r”。 2.然后,我将字节数组从起点剪切到该点,并使用它创建一个带有字符集的字符串(如果使用“new Stringbyte[]”或“new Stringbyte[],CharSet”指定)。 3.如果成功无例外,我们将找到第一个有效行并返回它。 4.否则,这些字节可能不是字符串,因此我进一步查看另一个“\n”或“\r”w/o”\n。这个过程会重复。 5.如果搜索在可用字节的末尾结束,我将停止并返回null未找到有效行

我的问题是,下面的算法是否足够

就在我即将实现它的时候,我在谷歌上搜索,发现新行还有很多其他代码,例如

所以我的最后一个问题是Q3,我真的需要检测这些代码吗?如果我这样做,是否会增加虚惊一场的机会

我很清楚,从二进制中识别某些东西并不是绝对的。我只是想找到最好的平衡

总之,我有一个字节数组,我想从中提取第一个有效的字符串行,带/不带特定的字符集。这必须在Java中完成,并避免使用任何非内置库


提前感谢大家。

java.text名称空间是为这种自然语言操作而设计的。getLineInstance静态方法返回检测换行符的迭代器。不过,您确实需要知道语言环境和编码才能获得最佳结果。

java.text名称空间是为这种自然语言操作而设计的。getLineInstance静态方法返回检测换行符的迭代器。不过,您确实需要知道区域设置和编码才能获得最佳结果。

Q2:您使用的方法似乎足够合理,可以工作

问题1:想不出比你正在使用的算法更好的方法了吗


问题3:我相信测试\r和\n就足够了。对于普通的文本文件来说,其他的方法太奇特了。

Q2:您使用的方法似乎足够合理

问题1:想不出比你正在使用的算法更好的方法了吗


问题3:我相信测试\r和\n就足够了。对于普通的文本文件来说,其他文件太离奇了。

恐怕您的问题没有明确定义。写下要从数据中提取第一个有效字符串行。但somet字节序列是否为有效字符串取决于编码。因此,您必须决定要在测试中使用哪些编码

明智的选择是:

平台默认编码Java属性文件.encoding UTF-8,因为它是最常见的 您知道客户将使用的编码列表,例如几种俄语或汉语编码 什么是有意义的将取决于数据,没有一般的答案

一旦你有了编码,行终止的问题就会随之而来,因为大多数编码都有终止行的规则。在ASCII或拉丁语-1中,LF、CR-LF和LF-CR就足够了。在Unicode上,您需要上面列出的所有代码


但是,由于新的行号没有受到严格的管制,所以也没有一般的答案。同样,这取决于您的数据。

恐怕您的问题没有明确定义。写下要从数据中提取第一个有效字符串行。但somet字节序列是否为有效字符串取决于编码。因此,您必须决定要在测试中使用哪些编码

明智的选择是:

平台默认编码Java属性文件.encoding UTF-8,因为它是最常见的 您知道客户将使用的编码列表,例如几种俄语或汉语编码 什么是有意义的将取决于数据,没有一般的答案

一旦你有了编码,行终止的问题就会随之而来,因为大多数编码都有终止行的规则。在ASCII或拉丁语-1中,LF、CR-LF和LF-CR就足够了。关于联通 e、 您需要上面列出的所有选项


但是,由于新的行号没有受到严格的管制,所以也没有一般的答案。同样,这取决于您的数据。

首先,让我问您一个问题,您试图处理的数据是遗留数据吗?换句话说,您是否负责您在这里尝试使用的输入流格式

如果您确实在控制输入格式,那么您可能希望从Q1算法中选择二进制与文本。对我来说,这个算法有一个麻烦的地方

    `4). Otherwise, these bytes may not be a string, so I look further to 
another '\n' or '\r' w/o '\n'. and this process repeat.`
您是在取消行终止符之前的输入并获取紧接其后开始的字节,还是尝试使用现在的两个行终止符重新计算字符串?如果是前者,您可能破坏了二进制数据接口,如果是后者,您可能仍然无法正确解析文本

我认为在流中为二进制数据和文本数据定义好标记将大大简化算法

字符串构造函数上的两个单词。如果字节数组不是特定的字符集,则新的Stringbyte[],字符集将不会生成任何异常,相反,它将创建一个充满问号的字符串(可能不是您想要的)。如果要生成异常,应使用

还要注意,在Java6中有2个构造函数接受字符集
Stringbyte[]字节,字符串字符集名称和Stringbyte[]字节,字符集字符集。不久前我做了一些简单的性能测试,使用字符串charsetName的构造函数比向Sun提出Charset对象问题的构造函数要快很多:bug,feature

首先让我问你一个问题,你试图处理的数据是遗留数据吗?换句话说,您是否负责您在这里尝试使用的输入流格式

如果您确实在控制输入格式,那么您可能希望从Q1算法中选择二进制与文本。对我来说,这个算法有一个麻烦的地方

    `4). Otherwise, these bytes may not be a string, so I look further to 
another '\n' or '\r' w/o '\n'. and this process repeat.`
您是在取消行终止符之前的输入并获取紧接其后开始的字节,还是尝试使用现在的两个行终止符重新计算字符串?如果是前者,您可能破坏了二进制数据接口,如果是后者,您可能仍然无法正确解析文本

我认为在流中为二进制数据和文本数据定义好标记将大大简化算法

字符串构造函数上的两个单词。如果字节数组不是特定的字符集,则新的Stringbyte[],字符集将不会生成任何异常,相反,它将创建一个充满问号的字符串(可能不是您想要的)。如果要生成异常,应使用

还要注意,在Java6中有2个构造函数接受字符集 Stringbyte[]字节,字符串字符集名称和Stringbyte[]字节,字符集字符集。不久前我做了一些简单的性能测试,使用字符串charsetName的构造函数比向Sun提出Charset对象问题的构造函数要快很多:bug,feature

我想试试这个:

使IO读取器将字符串/行放入线程安全的集合,例如BlockingQueue的一些实现 主代码仅引用同步的集合,并在需要时检查新数据,如queue.peek。它不需要了解io线程或流。 某些伪java代码缺少异常&io处理、泛型、导入++:

class IORunner extends Thread {
  IORunner(InputStream in, BlockingQueue outputQueue) {
    this.reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
    this.outputQueue = outputQueue;
  }

  public void run() {
    String line;
    while((line=reader.readLine())!=null)
      this.outputQueue.put(line);
  }
}

class Main {
  public static void main(String args[]) {
    ...
    BlockingQueue dataQueue = new LinkedBlockingQueue();
    new IORunner(myStreamFromSomewhere, dataQueue).start();

    while(true) {
      if(!dataQueue.isEmpty()) { // can also use .peek() != null
        System.out.println(dataQueue.take());
      }
      Thread.sleep(1000);
    }
  }
}
集合将inputstream与主代码进一步解耦。您还可以通过创建容量有限的队列来限制存储/mem使用的行数,请参阅blockingqueue doc。 BufferedReader为您处理新行的检查:InputStreamReader自己处理字符集建议设置,因为默认设置会根据操作系统等进行更改。。 我想试试这个:

使IO读取器将字符串/行放入线程安全的集合,例如BlockingQueue的一些实现 主代码仅引用同步的集合,并在需要时检查新数据,如queue.peek。它不需要了解io线程或流。 某些伪java代码缺少异常&io处理、泛型、导入++:

class IORunner extends Thread {
  IORunner(InputStream in, BlockingQueue outputQueue) {
    this.reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
    this.outputQueue = outputQueue;
  }

  public void run() {
    String line;
    while((line=reader.readLine())!=null)
      this.outputQueue.put(line);
  }
}

class Main {
  public static void main(String args[]) {
    ...
    BlockingQueue dataQueue = new LinkedBlockingQueue();
    new IORunner(myStreamFromSomewhere, dataQueue).start();

    while(true) {
      if(!dataQueue.isEmpty()) { // can also use .peek() != null
        System.out.println(dataQueue.take());
      }
      Thread.sleep(1000);
    }
  }
}
集合将inputstream与主代码进一步解耦。您还可以通过创建容量有限的队列来限制存储/mem使用的行数,请参阅blockingqueue doc。 BufferedReader为您处理新行的检查:InputStreamReader自己处理字符集建议设置,因为默认设置会根据操作系统等进行更改。。
我只是解决了这个问题,让测试stub为数据报工作——我做了byte[]varName=String.getBytes;然后final int len=varName.length;然后将int作为DataOutputStream发送,然后发送字节数组,只需在rcv上执行readInt,然后使用readInt读取字节计数

不是自由党,也不难做到。只需读取readUTF,并执行他们对字节所做的操作

字符串应该从恢复到w的字节数组中构造 嗯,如果不是的话,你还有其他问题。如果字符串可以重建,它可以被缓冲。。。没有

可以只在数据流中使用读/写UTF-为什么不

{编辑:每个OP的请求}

//Sending end 

String data = new String("fdsfjal;sajssaafe8e88e88aa");// fingers pounding keyboard
DataOutputStream dataOutputStream = new DataOutputStream();//
final Integer length = new Integer(data.length());
dataOutputStream.writeInt(length.intValue());//
dataOutputStream.write(data.getBytes());//
dataOutputStream.flush();//
dataOutputStream.close();//

// rcv end

DataInputStream dataInputStream = new DataInputStream(source);
final int sizeToRead = dataInputStream.readInt();
byte[] datasink = new byte[sizeToRead.intValue()];
dataInputStream.read(datasink,sizeToRead);
dataInputStream.close;
try
{
   // constructor
   // String(byte[] bytes, int offset, int length)

   final String result = new String(datasink,0x00000000,sizeToRead);//          

   // continue coding here

帮我个忙,别让我发火。这在发布工具中是非常快的-代码可能包含大量错误-对我来说,只是解释一下编写Java更快~如果您希望在另一个代码库中使用,还会有其他人可以将其翻译为其他代码语言。您将需要捕获异常,以此类推,只需进行编译并开始修复错误。当你得到一个干净的编译时,从头开始,寻找错误。这就是工程中所谓的错误——一个错误

我刚刚解决了这个问题,让测试stub为数据报工作——我做了byte[]varName=String.getBytes;然后final int len=varName.length;然后将int作为DataOutputStream发送,然后发送字节数组,只需在rcv上执行readInt,然后使用readInt读取字节计数

不是自由党,也不难做到。只需读取readUTF,并执行他们对字节所做的操作

如果没有其他问题,字符串应该从以这种方式恢复的字节数组中构造。如果字符串可以重建,它可以被缓冲。。。没有

可以只在数据流中使用读/写UTF-为什么不

{编辑:每个OP的请求}

//Sending end 

String data = new String("fdsfjal;sajssaafe8e88e88aa");// fingers pounding keyboard
DataOutputStream dataOutputStream = new DataOutputStream();//
final Integer length = new Integer(data.length());
dataOutputStream.writeInt(length.intValue());//
dataOutputStream.write(data.getBytes());//
dataOutputStream.flush();//
dataOutputStream.close();//

// rcv end

DataInputStream dataInputStream = new DataInputStream(source);
final int sizeToRead = dataInputStream.readInt();
byte[] datasink = new byte[sizeToRead.intValue()];
dataInputStream.read(datasink,sizeToRead);
dataInputStream.close;
try
{
   // constructor
   // String(byte[] bytes, int offset, int length)

   final String result = new String(datasink,0x00000000,sizeToRead);//          

   // continue coding here

帮我个忙,别让我发火。这在发布工具中是非常快的-代码可能包含大量错误-对我来说,只是解释一下编写Java更快~如果您希望在另一个代码库中使用,还会有其他人可以将其翻译为其他代码语言。您将需要捕获异常,以此类推,只需进行编译并开始修复错误。当你得到一个干净的编译时,从头开始,寻找错误。这就是工程学中所谓的错误——错误

谢谢你的回答。我看了一下,似乎我需要用字符串或字符来表示我的数据,这正是我无法理解的问题。谢谢你的回答。我看了一下,似乎我需要用字符串或characteristator来表示我的数据,这正是我无法理解的问题。谢谢你的回答。我在问题中提到,可能会使用包含编码信息的字符集。如果没有给出我在问题中没有提到的这个,我将使用默认值。关于unicode,您认为我应该尝试检测以上所有内容吗?再次感谢你的回答。没有默认字符集。@Jonathan:静态字符集。默认字符集非常接近,不是吗?请参阅。是的,该方法是存在的,但由于数据可能来自其他机器,因此该方法的结果与您机器上的结果不同,因此该方法没有用处。遗憾的是,API作者似乎不这么认为。看看所有那些不采用字符集的方法,默认为几乎总是错误的默认字符集:谢谢你的回答。我在问题中提到,可能会使用包含编码信息的字符集。如果没有给出我在问题中没有提到的这个,我将使用默认值。关于unicode,您认为我应该尝试检测以上所有内容吗?再次感谢你的回答。没有默认字符集。@Jonathan:静态字符集。默认字符集非常接近,不是吗?请参阅。是的,该方法是存在的,但由于数据可能来自其他机器,因此该方法的结果与您机器上的结果不同,因此该方法没有用处。遗憾的是,API作者似乎不这么认为。看看所有那些不采用字符集的方法,默认为几乎总是错误的默认字符集:感谢您的回答:D.1我正在创建一个非锁定输入流,我计划将其用于shell访问和网络连接,我无法控制。2我之所以选择另一个“\n”,是因为我认为0x0D和0x0A可能是有效UNICODE的一部分,我不确定。但以防万一,包含它的二进制文件可能是有效的一行字符串。这就是我为什么这么做的原因。3在我发布后,我发现了这一点,并改为CharsetDecoder:D。无论如何,谢谢你回答:D。1我正在创建一个非锁定输入流,我计划将其用于shell访问和网络连接,我无法控制。2我之所以选择另一个“\n”,是因为我认为0x0D和0x0A可能是有效UNICODE的一部分,我不确定。但以防万一,包含它的二进制文件可能是有效的一行字符串。这就是我为什么这么做的原因。3在我发布之后,我发现了这一点,并改为CharsetDecoder:D。无论如何,谢谢你的回答,但你介意给我看一些代码吗。简直无法想象-谢谢你,尼古拉斯。我同意你的建议
时间和精力。但在本例中,我无法控制字节的构造,因此无法发送字符串的长度。事实上,我甚至不知道它是否是一根我在第一次阅读时没有发现长度的字符串。使用readUTF似乎很有趣,因为Java会注意字节是否为字符串。我试试看。再次感谢您的帮助。听起来像是一个正则表达式问题,方法,无论您在www.regexbuddy.com和任何其他资源中找到什么,都要为开发工作中的突袭做好准备-我必须在几分钟内进入,但简要重读一下您的操作,这表明有一个String.split可以满足您的需要。手动编写自己的代码是可以做到的,但使用已有的工具可能会做得更多。应该有一个正则表达式可以在line.separator上拆分-您也可以使用阅读器以及java.sun.com/j2se/1.5.0/docs/api/java/util/Scanner.htmltanks来回答问题,但您介意给我看一些代码吗。简直无法想象-谢谢你,尼古拉斯。我占用你的时间和精力。但在本例中,我无法控制字节的构造,因此无法发送字符串的长度。事实上,我甚至不知道它是否是一根我在第一次阅读时没有发现长度的字符串。使用readUTF似乎很有趣,因为Java会注意字节是否为字符串。我试试看。再次感谢您的帮助。听起来像是一个正则表达式问题,方法,无论您在www.regexbuddy.com和任何其他资源中找到什么,都要为开发工作中的突袭做好准备-我必须在几分钟内进入,但简要重读一下您的操作,这表明有一个String.split可以满足您的需要。手动编写自己的代码是可以做到的,但使用已有的工具可能会做得更多。应该有一个regex在line.separator上拆分-您还可以使用读卡器以及java.sun.com/j2se/1.5.0/docs/api/java/util/Scanner.html