OutputStreamWriter 仅将一项写入文件

Posted

技术标签:

【中文标题】OutputStreamWriter 仅将一项写入文件【英文标题】:OutputStreamWriter only writing one item into file 【发布时间】:2021-12-06 05:04:40 【问题描述】:

我已使用以下代码将数组列表中的元素写入文件,以便稍后使用 StringTokenizer 检索。它适用于其他 3 个数组列表,但不知何故,它在使用 .nextToken() 读取时抛出异常,使用 .countTokens() 进行进一步故障排除表明文件中只有 1 个令牌。写入和读取的分隔符是相同的 - "," 与其他数组列表一样。

我很困惑为什么在我没有更改代码结构的情况下它不能像其他数组那样工作。

=================写入文件==================

public static void copy_TimeZonestoFile(ArrayList<AL_TimeZone> timezones, Context context)

    try 

        FileOutputStream fileOutputStream = context.openFileOutput("TimeZones.dat",Context.MODE_PRIVATE);
        OutputStreamWriter writerFile = new OutputStreamWriter(fileOutputStream);

        int TZsize = timezones.size();

        for (int i = 0; i < TZsize; i++) 
            writerFile.write(
                    timezones.get(i).getRegion() + "," +
                            timezones.get(i).getOffset() + "\n"
            );
        

        writerFile.flush();
        writerFile.close();

     catch (FileNotFoundException e) 
        e.printStackTrace();
     catch (IOException e) 
        e.printStackTrace();
    

==========从文件中读取(嵌套在线程/可运行组合中)===========

        public void run() 


            if (fileTimeZones.exists())

                System.out.println("Timezone file exists. Loading.. File size is : " + fileTimeZones.length());
                try

                    savedTimeZoneList.clear();

                    BufferedReader reader = new BufferedReader(new InputStreamReader(openFileInput("TimeZones.dat")));
                    String lineFromTZfile = reader.readLine();
                    while (lineFromTZfile != null )
                        StringTokenizer token = new StringTokenizer(lineFromTZfile,",");
                        AL_TimeZone timeZone = new AL_TimeZone(token.nextToken(),
                                token.nextToken());

                        savedTimeZoneList.add(timeZone);
                    


                 catch (FileNotFoundException e) 
                    e.printStackTrace();
                 catch (IOException e) 
                    e.printStackTrace();
                 catch (Exception e)
                    e.printStackTrace();
                
            
        

===================Trace=======================

I/System.out: Timezone file exists. Loading.. File size is : 12373
W/System.err: java.util.NoSuchElementException
    at java.util.StringTokenizer.nextToken(StringTokenizer.java:349)
    at com.cryptotrac.trackerService$1R_loadTimeZones.run(trackerService.java:215)
W/System.err:     at java.lang.Thread.run(Thread.java:764)

【问题讨论】:

AL_TimeZone 是什么样子的,它的 region 和 offset 字段的值是多少? @Abra 从描述中我很确定在解析第二行时它是 NoSuchElementException 。但是,还是不错的建议。 AL_TimeZone 只是一个包含 2 个字符串元素的 ArrayList。比其他混合了 int、double、strings 等的人要简单得多。用相关的跟踪更新了问题。 【参考方案1】:

您的这行代码似乎导致java.util.NoSuchElementException 被抛出。

AL_TimeZone timeZone = new AL_TimeZone(token.nextToken(), token.nextToken());

这可能意味着文件 TimeZones.dat 中至少有一行不包含由单个逗号分隔的两个字符串。

这可以通过在尝试解析之前确保从文件中读取的行是有效行来轻松检查。

使用java.lang.String 类的方法split 优于使用StringTokenizer。事实上,StringTokenizer 类的 javadoc 声明如下。

StringTokenizer 是一个遗留类,出于兼容性原因保留,但不鼓励在新代码中使用它。建议任何寻求此功能的人使用 String 的 split 方法或 java.util.regex 包。

试试下面的。

String lineFromTZfile = reader.readLine();
while (lineFromTZfile != null )
    String[] tokens = lineFromTZfile.split(",");
    if (tokens.length == 2) 
        // valid line, proceed to handle it
    
    else 
        // optionally handle an invalid line - maybe write it to the app log
    
    lineFromTZfile = reader.readLine(); // Read next line in file.

【讨论】:

感谢您的建议。我也尝试了这种方法,但仍然被发送到 ELSE 路线。认为问题真的出现在写作部分。尽管如此,它仍将替换 StringTokenizer 方法。谢谢! @xv.ch 如果您希望我帮助您调试代码,请编辑您的问题并发布文件 TimeZones.dat 的内容。发布minimal reproducible example 也可以帮助我调试您的代码。【参考方案2】:

可能有多处错误,因为我实际上希望您会陷入无限循环,因为您只是读取文件的第一行,然后反复解析它。

您应该检查以下事项:

确保正确写入文件。书面文件究竟包含什么?每行末尾是否有新行? 确保写入的数据(在本例中为“region”和“offset”)绝不包含逗号,否则解析将中断。我认为“区域”包含逗号的可能性很大。 读取文件时,您总是需要假设文件(格式)已损坏。例如,假设 readLine 将返回一个空行或包含多于或少于一个逗号的内容。

【讨论】:

我试过用!作为分隔符以及仍然不起作用。在区域和偏移量中,唯一的非字母字符是“_”、“/”和“+”。它们是否会影响 StringTokenizer 方法?根据代码,应该读取文件直到文件的最后一行结束。我不认为这部分有什么问题,因为它在其他 3 个数组中使用相同的代码。 偏移量也包含“-”和“:”。

以上是关于OutputStreamWriter 仅将一项写入文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Latex 中仅将一位作者与其他三位作者居中对齐

输出流FileWriter和FileInputStream,和一个可以处理中文的OutputStreamWriter,如果要对中文进行传输和写入用OutputStreamWriter和InputStr

JavaSE8基础 OutputStreamWriter flush 写入字符后要刷新缓冲区

仅将 Hadoop MapReduce 输出写入 2 个平面文件

为啥仅将数据写入 Firebase 数据库的下载成本为 12kB/分钟?

如何仅将所有error_logs写入php中的一个文件