【问题标题】:Java make file reader account for specific lettersJava为特定字母制作文件阅读器
【发布时间】:2015-10-10 04:14:00
【问题描述】:

感谢这个伟大的社区,我的世界编辑器几乎完成了,我唯一需要知道的是如何告诉我读取的文件代码来处理特定的字母。当我在键盘上按 Enter 键时,我会将 Vector3f 的坐标写入文本文件,这个 Vector3f 是我的活动游戏对象的位置。我的 ProcessText 方法可以读取文本文件并处理坐标,但是他只能读取任何类型的格式:

public void ProcessText()
     {      
        String file_name = "C:/Users/Server/Desktop/textText.txt";

        try
        {           
            ProcessCoords file = new ProcessCoords(file_name);
            String[] aryLines = file.OpenFile();

            int i;
            for (i = 0; i < aryLines.length; i++)
            {
                System.out.println(aryLines[i]);    

                 if(aryLines[i].startsWith("makeGrass:")) {
                        String Arguments = aryLines[i].substring(aryLines[i].indexOf(":")+1, aryLines[i].length());
                        String[] ArgArray = Arguments.split(",");

                        this.makeGrass(Double.parseDouble(ArgArray[0]), 
                                       Double.parseDouble(ArgArray[1]), 
                                       Double.parseDouble(ArgArray[2]));                    
                }
            }   
        } catch(IOException e) {
            System.out.println(e.getMessage());
        }
     }

在上面的例子中,我的 ProcessText 方法只能处理这样写的坐标:

makeGrass:x,y,z             //for example makeGrass:5,1,9

但是当我按下回车键并写下我的引擎给出的坐标时,我得到了不同的格式:

makeGrass:(x y z)           //for example makeGrass:(3 1 4)

现在我需要知道的是,我必须如何重写我的 ProcessText 方法中的代码,以便它解释在开头和结尾有括号的另一种格式,以及用空格将 x 从 y 和 y 从 z 分隔逗号。

我真的不知道在哪里可以找到这个问题的答案,所以我很感谢任何关于它如何工作的帮助和解释。

提前非常感谢!

【问题讨论】:

  • ArgArray = Arguments.substring(1, Arguments.length() - 2).split(" ");

标签: java filereader account letter


【解决方案1】:

只需用正则表达式拆分:[\s,] 在存在white space, 的位置拆分字符串。

如果存在的话,用它来去掉任何括号:

Arguments = Arguments.replaceAll("\\(", "").replaceAll("\\)", "");

() 是正则表达式的一部分。因此,它们需要使用\\ 作为Java 表示法进行转义,需要使用另一种\ 进行转义。因此它变成了`"\("。我们必须替换字符串并将其存储回String变量。因为Java是按值传递的。两个操作都在同一行中完成。

该方法的修改代码为:

public void ProcessText() {      
     String file_name = "C:/Users/Server/Desktop/textText.txt";



public void ProcessText()
 {      
    String file_name = "C:/Users/Server/Desktop/textText.txt";

    try
    {           
        ProcessCoords file = new ProcessCoords(file_name);
        String[] aryLines = file.OpenFile();

        int i;
        for (i = 0; i < aryLines.length; i++)
        {
            System.out.println(aryLines[i]);    

             if(aryLines[i].startsWith("makeGrass:")) {
                    String Arguments = aryLines[i].substring(aryLines[i].indexOf(":")+1, aryLines[i].length());

                    Arguments = Arguments.replaceAll("\\(", "").replaceAll("\\)", "");

                    String[] ArgArray = Arguments.split("[\\s,]");


                    this.makeGrass(Double.parseDouble(ArgArray[0]), 
                                   Double.parseDouble(ArgArray[1]), 
                                   Double.parseDouble(ArgArray[2])); 
            }
        }   
    } catch(IOException e) {
        System.out.println(e.getMessage());
    }
 } 

【讨论】:

  • 好的,但这是否也考虑了括号?它是 makeGrass:(x y z) 不仅仅是 makeGRass:x y z .. 但感谢您的提示!
  • 您好,我认为这可能有效,但您的代码给了我一个错误:Arguments.replaceAll("(", ""); 它说命名序列无效..?
  • 我已经更正了。并且也检查过。这将起作用。当然。这是我的错误。我忽略了 2 \s。我之前只放了1个。它需要被转义。
【解决方案2】:

您想接受尽可能多的格式吗?

我会尝试匹配而不是拆分,这更安全,并且不需要对输入或接收到的子字符串进行任何预处理或后处理:

Pattern pattern = Pattern.compile("([0-9]+)"); // outside of method

long[] ArgArray = new long[3];
Matcher matcher = pattern.matcher(Arguments);
int i = 0;
while (matcher.find() && i < 3) {
   ArgArray[i++] = Long.parseLong(matcher.group(1));
}
// there was a mistake if i < 3, otherwise you have 3 numbers in ArgArray

如果你想拆分,你可以试试这个:split("[^0-9]+")

只匹配 makeGrass:(x y z)

Pattern pattern = Pattern.compile("^makeGrass:\\(([0-9]+) ([0-9]+) ([0-9]+)\\)$");

像这样,您可以直接匹配该行并在调用find 一次后将 3 个数字分成 1 - 3 组(作为字符串),if (matcher.find()) 将决定它是否是有效的 makeGrass 行,如果是则可以处理在if

【讨论】:

  • 不,我不想接受尽可能多的格式,只有 makeGrass:(xyz) 是必要的,但我也对它的工作原理感兴趣,因为将来我可能想写信给从文件中读取其他内容,而不仅仅是像这种情况下的一些坐标。但是感谢您的提示!
  • @DisasterCoder 好的,我添加了另一个版本,它只是正则表达式(\ 必须加倍,因为它也是 Java 字符串中的转义字符)。
  • 谢谢,我会尽快尝试,只有一件事:数字是浮动的,通常坐标会像 (1.23333 1.56665 5.88769) 或类似的东西..这仍然有效如果你只声明从零到九?
  • @DisasterCoder 否,然后使用 ([0-9]+\\.[0-9]+),如果 .那么您可以删除第一个 + 并且如果必须在 .然后将第二个 + 替换为 {5}
  • 或者如果第二部分是可选的([0-9]\\.?[0-9]*)
【解决方案3】:

如果你能保证 makeGrass:x,y,z 格式中不会有任何空格并且其中也不会有任何括号,那么你可以使用 String.replaceAll()... 如下所示:

myString = "makeGrass:(3 1 4)"
myString = myString.replaceAll("\(", ""); //replace ( with empty space
myString = myString.replaceAll("\)", ""); //replace ) with empty space
myString = myString.replaceAll(" ", ","); //replace spaces with commas

那么您不需要不同的方法来处理这两种类型的输入。只需如上所示格式化并将两个输入传递给相同的方法

这样你就不需要分割某些字符然后重建字符串以适应你的格式

【讨论】:

  • 我不太明白你在告诉我什么,你是否建议我改变坐标写入文件的方式?因为如果是这样,那么我不得不说这将比我认为的要复杂得多.. 但也许你可以告诉我你认为这段代码如何适合我的 ProcessText 方法,因为我真的不明白我是如何应该实现你的代码..?
  • 所以你的程序会读入输入,假设输入是 makeGrass:(3 1 4)...输入 makeGrass:3,1,4 的正确格式,然后你可以像以前一样处理它
  • 我认为这不会那么容易,因为写入文件在这里使用以下代码: data.writeToFile("makeGrass:" + (GetTransform().GetPos()));为了获得坐标,我使用了我的引擎的 Transform 类,它可以访问 Vector3f 方法。我认为我没有足够的经验将您的想法实施到我的代码中..
  • 或者我只是感到困惑 - 一定会尝试一下......谢谢!
  • 是的,这里是一样的。我收到错误消息,我使用了错误的结束序列类型,错误标记在歌曲周围(不知道如何解决这个问题.. ?
猜你喜欢
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-11
  • 1970-01-01
  • 2016-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多