Java:如何将传入的数据片段收集到正确终止的字符串中以供后续解析?

发布于 2024-09-25 09:39:35 字数 2843 浏览 4 评论 0原文

在过去在这里找到了许多很好的答案后,我刚刚加入了 StackOverflow。这是我的第一个问题:

编辑:我感觉很糟糕......我向 StackOverflow 提出的第一个问题结果是“徒劳无功”。问题出在数据,而不是读取数据的代码。我在错误的地方寻找解决方案!我会在下面的评论中解释。

请忽略这个问题。

在我的应用程序中,数据以片段形式到达(它是串行数据)。我想将数据传递给解析它的方法。但我只想传递正确终止的线路。这些行将以“\r”(返回字符)终止。有时,输入的数据片段具有多个终止行。但有时传入的数据片段还没有终止符(终止符稍后会到达)。

我的目标是能够仅将正确终止的行(完整行)发送到 dataProcessor.logSerialData。 (代码可以在没有这个要求的情况下工作,但是如果我能够满足这个要求,我可以编写更清晰的代码。解析逻辑 - 此处未显示 - 会更容易维护。)

这是我的代码,可以工作(但不能满足我的新要求):

case SerialPortEvent.DATA_AVAILABLE:
            try
            {
                int len = -1;
                while ((len = in.read(readBuffer)) > 0)
                {
                    if (len > 0)
                    {
                        String s = new String(readBuffer, 0, len);
                        if (dataProcessor != null)
                        {
                            dataProcessor.logSerialData(s);
                        }
                        else
                        {
                            Logger.log("ERROR: packetReceiver is null");
                        }
                    }
                }
            }
            catch (IOException ex)
            {
                Logger.log(ex);
                return;
            }

这是我尝试过的许多不起作用的事情之一的示例。它以某种方式导致数据流中的错误。

private static final String REGEX = ".*\\r";
private Pattern p = Pattern.compile(REGEX);

public void serialEvent(SerialPortEvent e)
{
    byte[] readBuffer = new byte[11000];//tried many values for buffer size

    switch (e.getEventType())
    {
        case SerialPortEvent.DATA_AVAILABLE:
            try
            {
                int len = -1;
                while ((len = in.read(readBuffer)) > 0)
                {
                    if (len > 0)
                    {
                        String input = new String(readBuffer, 0, len);
                        Matcher m = p.matcher(input);
                        int count = 0;
                        while (m.find())
                        {
                            count++;
                            String terminatedLine = m.group();
                            if (!terminatedLine.isEmpty())
                            {
                                completedLines.add(terminatedLine);
                            }
                        }
                    }
                }
            }
            catch (IOException ex)
            {
                Logger.log(ex);
                return;
            }
            for (String line : completedLines)
            {
                dataProcessor.logSerialData(line);
            }

有什么建议吗? (事实上​​,知道为什么新代码会在数据流中引入错误吗?我尝试过的工作代码的每个变体都无法正常工作。我尝试过正则表达式和非正则表达式方法以及任何其他方法。唯一的代码上面显示的工作示例似乎非常棘手,我需要一些帮助。

I just joined StackOverflow after having found many great answers here in the past. Here's my first question:

EDIT: I feel bad... my first question to StackOverflow turned out to be a "wild goose chase". The problem is in the data, not the code reading the data. I was looking for a solution in the wrong place! I will explain in a comment below.

Please disregard this question.

In my application, data arrives in fragments (it is serial data). I want to pass the data along to a method that will parse it. But I only want to pass along properly terminated lines. The lines will be terminated by '\r' (return char). Sometimes a fragment of data comes in that has multiple terminated lines. But sometimes a fragment of data comes in that doesn't yet have a terminator (the terminator will arrive later).

My goal is to be able to send only properly terminated lines (complete lines) to dataProcessor.logSerialData. (The code works without this requirement, but I could write much cleaner code if I could meet this requirement. The parsing logic -- not shown here -- would be easier to maintain.)

Here is my code that DOES work (but does not meet my new requirement):

case SerialPortEvent.DATA_AVAILABLE:
            try
            {
                int len = -1;
                while ((len = in.read(readBuffer)) > 0)
                {
                    if (len > 0)
                    {
                        String s = new String(readBuffer, 0, len);
                        if (dataProcessor != null)
                        {
                            dataProcessor.logSerialData(s);
                        }
                        else
                        {
                            Logger.log("ERROR: packetReceiver is null");
                        }
                    }
                }
            }
            catch (IOException ex)
            {
                Logger.log(ex);
                return;
            }

Here is an example of one of the many things I tried that does NOT work. It somehow causes errors in the data stream.

private static final String REGEX = ".*\\r";
private Pattern p = Pattern.compile(REGEX);

public void serialEvent(SerialPortEvent e)
{
    byte[] readBuffer = new byte[11000];//tried many values for buffer size

    switch (e.getEventType())
    {
        case SerialPortEvent.DATA_AVAILABLE:
            try
            {
                int len = -1;
                while ((len = in.read(readBuffer)) > 0)
                {
                    if (len > 0)
                    {
                        String input = new String(readBuffer, 0, len);
                        Matcher m = p.matcher(input);
                        int count = 0;
                        while (m.find())
                        {
                            count++;
                            String terminatedLine = m.group();
                            if (!terminatedLine.isEmpty())
                            {
                                completedLines.add(terminatedLine);
                            }
                        }
                    }
                }
            }
            catch (IOException ex)
            {
                Logger.log(ex);
                return;
            }
            for (String line : completedLines)
            {
                dataProcessor.logSerialData(line);
            }

Any suggestions? (In fact, any idea why the new code introduces errors into the data stream? Every variation of the working code that I have tried does not work correctly. I have tried regex and non-regex methods and any other things. The only code that works is the working example shown above. Serial data processing seems very tricky! I could use some help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤独患者 2024-10-02 09:39:35

这应该可以根据需要工作。

private String remains = "";
...

int len = -1;
while ((len = in.read(readBuffer)) > 0) {
    if (len > 0) {
        String input = remains + new String(readBuffer, 0, len);
        Matcher m = p.matcher(input);
        int last = 0;
        while (m.find()) {
            String terminatedLine = m.group();
            last = m.end(0);
            if (!terminatedLine.isEmpty()) completedLines.add(terminatedLine);
        }
        remains = input.substring(last);
    }
}

This should work as needed.

private String remains = "";
...

int len = -1;
while ((len = in.read(readBuffer)) > 0) {
    if (len > 0) {
        String input = remains + new String(readBuffer, 0, len);
        Matcher m = p.matcher(input);
        int last = 0;
        while (m.find()) {
            String terminatedLine = m.group();
            last = m.end(0);
            if (!terminatedLine.isEmpty()) completedLines.add(terminatedLine);
        }
        remains = input.substring(last);
    }
}
不离久伴 2024-10-02 09:39:35

是否可以将 InputStream 包装到 ReaderBufferedReader 中并从中读取行?

It is possible to wrap the InputStream into a Reader into a BufferedReader and read lines from that?

生生漫 2024-10-02 09:39:35

各种逐行阅读的方法都不起作用。最初的方法之所以有效,只是因为它不寻找行终止符。

当我发现所有“万无一失”的方法都没有达到预期的效果后,我做了进一步的调查。似乎输入数据中的行终止符存在一些不一致。 Java 会在不应该存在的地方看到终止符,并错过那里的终止符。

在花了几天时间之后,我想我将回到原来的方法,该方法无需寻找行终止符即可工作。

很抱歉问了一个虚假的问题。

None of the various methods of reading by lines worked. The original method worked only because it did not look for line terminators.

Upon seeing that none of the "sure fire" methods worked predictably, I did further investigation. It seems that there is some inconsistency in the incoming data with regard to line terminators. Java sees terminators where there should not be any, and misses terminators that are there.

After spending several days on this, I think I'm just going to go back to the original method that worked without looking for line terminators.

Sorry for the bogus question.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文