代码之家  ›  专栏  ›  技术社区  ›  NawaMan

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

  •  1
  • NawaMan  · 技术社区  · 16 年前

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

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

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

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

    我的问题是( 问题2 )以下算法是否足够?

    U+2424 , U+0085, U+000C, U+2028 and U+2029 .

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

    提前谢谢大家。

    6 回复  |  直到 16 年前
        1
  •  4
  •   sleske    16 年前

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

    • 平台默认编码(Java属性“file.encoding”)
    • 您知道客户将使用的编码列表(如几种俄语或汉语编码)

    什么是有意义的将取决于数据,没有一般的答案。

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

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

        2
  •  2
  •   Alexander Pogrebnyak    16 年前

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

        `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.`
    

    您是在取消行终止符之前的输入并获取紧接其后开始的字节,还是尝试使用现在的两个行终止符重新计算字符串?如果是前者,您可能破坏了二进制数据接口,如果是后者,您可能仍然无法正确解析文本。

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

    字符串构造函数上的两个单词。 new String(byte[], CharSet) CharsetDecoder .

    还要注意,在Java6中有2个构造函数接受字符集 String(byte[] bytes, String charsetName) String(byte[] bytes, Charset charset) . 不久前我做了一些简单的性能测试,并使用 String Charset 对象(向Sun提出的问题:bug、功能?)。

        3
  •  1
  •   Steve Gilham    16 年前

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

        4
  •  1
  •   rslite    16 年前

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

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

        5
  •  1
  •   Melv    16 年前

    我想试试这个:

    一些 伪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);
        }
      }
    }
    
    • 集合将输入(流)与主代码进一步分离。您还可以通过创建容量有限的队列来限制存储/mem使用的行数(请参阅blockingqueue文档)。
    • BufferedReader为您处理新行的检查:)InputStreamReader处理字符集(建议您自己设置一个,因为默认的字符集会根据操作系统等进行更改)。
        6
  •  1
  •   Nicholas Jordan    16 年前

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

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

    可能只需要在数据流中使用读/写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更快~如果您希望在另一个代码库中使用,也可以将其翻译为其他代码语言。您将需要捕获异常,以此类推,只需进行编译并开始修复错误。当你得到一个干净的编译时,从头开始,寻找错误。(这就是工程学中所谓的错误——错误)