读取文件——将字符串和 int 值配对——使用多条分割线
Reading a file -- pairing a String and int value -- with multiple split lines
我正在按照以下标准进行练习:
“输入由成对的标记组成,其中每对标记以该人购买的机票类型(“长途汽车”、“头等舱”或“折扣”,区分大小写)和后面是飞行的里程数。"
列表可以配对 -- coach 1500 firstclass 2000 discount 900 coach 3500
-- 目前效果很好。但是,当 String 和 int 值像这样拆分时:
firstclass 5000 coach 1500 coach
100 firstclass
2000 discount 300
它完全坏了。我几乎可以肯定跟我用这个格式有关系(不全)
while(fileScanner.hasNextLine())
{
StringTokenizer token = new StringTokenizer(fileScanner.nextLine(), " ")
while(token.hasMoreTokens())
{
String ticketClass = token.nextToken().toLowerCase();
int count = Integer.parseInt(token.nextToken());
...
}
}
因为它总是将第一个值读取为字符串,将第二个值读取为整数。我非常不知道如何在阅读下一行时跟踪一个或另一个。非常感谢任何帮助。
类似(我认为)的问题:
- Efficient reading/writing of key/value pairs to file in Java
- Reading multiple values in multiple lines from file (Java)
如果您有能力一次读取一个非常长的文本文件 String
,只需使用 built-in String.split()
和正则表达式 \s+
,像这样
String[] tokens = fileAsString.split("\s+");
这会将输入文件拆分为标记,假设标记由一个或多个 whitespace 字符分隔(白色 space 字符包括换行符、space、制表符和马车 return)。偶数和奇数标记分别是机票类型和里程数。
如果您绝对必须读入 line-by-line 并使用 StringTokenizer
,一个解决方案是计算最后一行中的标记数。如果这个数字是奇数,则当前行中的第一个标记将是最后一行中第一个标记的不同类型。一旦知道当前行的起始类型,只需从那里交替类型。
int tokenCount = 0;
boolean startingType = true; // true for String, false for integer
boolean currentType;
while(fileScanner.hasNextLine())
{
StringTokenizer token = new StringTokenizer(fileScanner.nextLine(), " ");
startingType = startingType ^ (tokenCount % 2 == 1); // if tokenCount is odd, the XOR ^ operator will flip the starting type of this line
tokenCount = 0;
while(token.hasMoreTokens())
{
tokenCount++;
currentType = startingType ^ (tokenCount % 2 == 0); // alternating between types in current line
if (currentType) {
String ticketClass = token.nextToken().toLowerCase();
// do something with ticketClass here
} else {
int mileCount = Integer.parseInt(token.nextToken());
// do something with mileCount here
}
...
}
}
我找到了另一种不使用 StringTokenizer 或正则表达式来解决这个问题的方法...诚然,我在使用正则表达式时遇到了麻烦哈哈。
我在 try-catch 块之外声明这些,因为我想在我的 finally 语句和 return 点中使用它们:
int points = 0;
ArrayList<String> classNames = new ArrayList<>();
ArrayList<Integer> classTickets = new ArrayList<>();
然后在我的 try-statement 中,我声明了 index
变量,因为我在这个块之外不需要它。每次读取新元素时,该变量都会增加。奇数元素被读取为票价classes,偶数元素被读取为票价:
try
{
int index = 0;
// read till the file is empty
while(fileScanner.hasNext())
{
// first entry is the ticket type
if(index % 2 == 0)
classNames.add(fileScanner.next());
// second entry is the number of points
else
classTickets.add(Integer.parseInt(fileScanner.next()));
index++;
}
}
您可以像这样在此处捕获它,也可以在您的方法声明中使用 throws NoSuchElementException
-- 只要您在方法调用时捕获它
catch(NoSuchElementException noElement)
{
System.out.println("<###-NoSuchElementException-###>");
}
然后到这里,遍历元素的数量。查看是哪个航班 class 并分别乘以票数和 return 街区外的点数:
finally
{
for(int i = 0; i < classNames.size(); i++)
{
switch(classNames.get(i).toLowerCase())
{
case "firstclass": // 2 points for first
points += 2 * classTickets.get(i);
break;
case "coach": // 1 point for coach
points += classTickets.get(i);
break;
default:
// budget gets nothing
}
}
}
return points;
正则表达式似乎是最方便的方式,但出于某种原因,这对我来说更直观。不管怎样,希望综艺能有所帮助。
simply use the built-in String.split() - @bui
我终于能够理解正则表达式了,但是 \s+ 由于某种原因没有被识别。它一直给我这个错误信息:
Invalid escape sequence (valid ones are \b \t \n \f \r " ' \ )Java(1610612990)
因此,当我改用这些字符时,我可以这样写:
int points = 0, multiplier = 0, tracker = 0;
while(fileScanner.hasNext())
{
String read = fileScanner.next().split(
"[\b \t \n \f \r \" \' \ ]")[0];
if(tracker % 2 == 0)
{
if(read.toLowerCase().equals("firstclass"))
multiplier = 2;
else if(read.toLowerCase().equals("coach"))
multiplier = 1;
else
multiplier = 0;
}else
{
points += multiplier * Integer.parseInt(read);
}
tracker++;
}
此代码一次进入一个条目,而不是读取整个空白数组作为 work-around 我收到的错误消息。如果您能告诉我使用 String[] tokens = fileAsString.split("\s+");
代码会是什么样子,我将不胜感激 :)
you need to add another "\" before "\s" to escape the slash before "s" itself – @bui
我正在按照以下标准进行练习:
“输入由成对的标记组成,其中每对标记以该人购买的机票类型(“长途汽车”、“头等舱”或“折扣”,区分大小写)和后面是飞行的里程数。"
列表可以配对 -- coach 1500 firstclass 2000 discount 900 coach 3500
-- 目前效果很好。但是,当 String 和 int 值像这样拆分时:
firstclass 5000 coach 1500 coach
100 firstclass
2000 discount 300
它完全坏了。我几乎可以肯定跟我用这个格式有关系(不全)
while(fileScanner.hasNextLine())
{
StringTokenizer token = new StringTokenizer(fileScanner.nextLine(), " ")
while(token.hasMoreTokens())
{
String ticketClass = token.nextToken().toLowerCase();
int count = Integer.parseInt(token.nextToken());
...
}
}
因为它总是将第一个值读取为字符串,将第二个值读取为整数。我非常不知道如何在阅读下一行时跟踪一个或另一个。非常感谢任何帮助。
类似(我认为)的问题:
- Efficient reading/writing of key/value pairs to file in Java
- Reading multiple values in multiple lines from file (Java)
如果您有能力一次读取一个非常长的文本文件 String
,只需使用 built-in String.split()
和正则表达式 \s+
,像这样
String[] tokens = fileAsString.split("\s+");
这会将输入文件拆分为标记,假设标记由一个或多个 whitespace 字符分隔(白色 space 字符包括换行符、space、制表符和马车 return)。偶数和奇数标记分别是机票类型和里程数。
如果您绝对必须读入 line-by-line 并使用 StringTokenizer
,一个解决方案是计算最后一行中的标记数。如果这个数字是奇数,则当前行中的第一个标记将是最后一行中第一个标记的不同类型。一旦知道当前行的起始类型,只需从那里交替类型。
int tokenCount = 0;
boolean startingType = true; // true for String, false for integer
boolean currentType;
while(fileScanner.hasNextLine())
{
StringTokenizer token = new StringTokenizer(fileScanner.nextLine(), " ");
startingType = startingType ^ (tokenCount % 2 == 1); // if tokenCount is odd, the XOR ^ operator will flip the starting type of this line
tokenCount = 0;
while(token.hasMoreTokens())
{
tokenCount++;
currentType = startingType ^ (tokenCount % 2 == 0); // alternating between types in current line
if (currentType) {
String ticketClass = token.nextToken().toLowerCase();
// do something with ticketClass here
} else {
int mileCount = Integer.parseInt(token.nextToken());
// do something with mileCount here
}
...
}
}
我找到了另一种不使用 StringTokenizer 或正则表达式来解决这个问题的方法...诚然,我在使用正则表达式时遇到了麻烦哈哈。
我在 try-catch 块之外声明这些,因为我想在我的 finally 语句和 return 点中使用它们:
int points = 0;
ArrayList<String> classNames = new ArrayList<>();
ArrayList<Integer> classTickets = new ArrayList<>();
然后在我的 try-statement 中,我声明了 index
变量,因为我在这个块之外不需要它。每次读取新元素时,该变量都会增加。奇数元素被读取为票价classes,偶数元素被读取为票价:
try
{
int index = 0;
// read till the file is empty
while(fileScanner.hasNext())
{
// first entry is the ticket type
if(index % 2 == 0)
classNames.add(fileScanner.next());
// second entry is the number of points
else
classTickets.add(Integer.parseInt(fileScanner.next()));
index++;
}
}
您可以像这样在此处捕获它,也可以在您的方法声明中使用 throws NoSuchElementException
-- 只要您在方法调用时捕获它
catch(NoSuchElementException noElement)
{
System.out.println("<###-NoSuchElementException-###>");
}
然后到这里,遍历元素的数量。查看是哪个航班 class 并分别乘以票数和 return 街区外的点数:
finally
{
for(int i = 0; i < classNames.size(); i++)
{
switch(classNames.get(i).toLowerCase())
{
case "firstclass": // 2 points for first
points += 2 * classTickets.get(i);
break;
case "coach": // 1 point for coach
points += classTickets.get(i);
break;
default:
// budget gets nothing
}
}
}
return points;
正则表达式似乎是最方便的方式,但出于某种原因,这对我来说更直观。不管怎样,希望综艺能有所帮助。
simply use the built-in String.split() - @bui
我终于能够理解正则表达式了,但是 \s+ 由于某种原因没有被识别。它一直给我这个错误信息:
Invalid escape sequence (valid ones are \b \t \n \f \r " ' \ )Java(1610612990)
因此,当我改用这些字符时,我可以这样写:
int points = 0, multiplier = 0, tracker = 0;
while(fileScanner.hasNext())
{
String read = fileScanner.next().split(
"[\b \t \n \f \r \" \' \ ]")[0];
if(tracker % 2 == 0)
{
if(read.toLowerCase().equals("firstclass"))
multiplier = 2;
else if(read.toLowerCase().equals("coach"))
multiplier = 1;
else
multiplier = 0;
}else
{
points += multiplier * Integer.parseInt(read);
}
tracker++;
}
此代码一次进入一个条目,而不是读取整个空白数组作为 work-around 我收到的错误消息。如果您能告诉我使用 String[] tokens = fileAsString.split("\s+");
代码会是什么样子,我将不胜感激 :)
you need to add another "\" before "\s" to escape the slash before "s" itself – @bui