【问题标题】:How do I validate text file contents in Java?如何在 Java 中验证文本文件内容?
【发布时间】:2023-03-18 18:34:01
【问题描述】:

我正在创建一个读取 .txt 文件内容的程序,它会验证该文件的内容,然后将该文件的内容输出到一个格式良好的表格中。我的程序当前读取文件然后输出内容,我正在尝试实现对所述文件内容的验证。

我现在将解释我的程序读取文件的方式:

.txt 内容:

firstname lastname
Gameone : 120 : 1428 
Gametwo : 20 : 10 
Gamethree : 90 : 800 
Gamefour : 190 : 2001 
Gamefive : 25 : 80 
Gamesix : 55 : 862

txt 文件包含这种格式的数据:

{gamename} : {gamescore} : {minutesplayed}

要阅读我使用的 .txt:

 System.out.println("*FILE HAS BEEN LOCATED*");
    System.out.println("*File contains: \n");
    while(scan.hasNext()) 
    {
        a = scan.nextLine();
        b = scan.nextLine();
        c = scan.nextLine();
        d = scan.nextLine();
        e = scan.nextLine();
        f = scan.nextLine();
        g = scan.nextLine();
    }

然后拆分数据,我在每个字母上从 a 到 g 使用这个 for 循环,如下所示:

    //~~~~a-line-split~~~~//
    String[] aline;

    aline = a.split(":");

    for (int i=0; i<aline.length; i++)
    {
        aline[i] = aline[i].trim();
        //System.out.println(aline[i]);
    }

为了通过验证进行澄清,我需要通知用户一行中是否缺少数据,例如第一行是否有:

gameone : {missing} : 1428

目前我对每一行都有这个简单的 if 语句:

            if (bline.length < 3)
            {
                System.out.println("There is an error in row one!");
            }

但是,我需要程序准确地知道每行数据丢失的位置。不只是一般的回应:

     System.out.println("There is an error in row one!");

但实际上是这样的:

     System.out.println("There is data missing, row: 1 column: 2");

根据要求提供完整代码:

    package readfile;

    import java.io.*;
    import java.util.*;

    public class readfile 
     {

     public static void main(String[] args)

     {
    Scanner scan = new Scanner (System.in);
    String FileN = " ";
    String a = " ";
    String b = " ";
    String c = " ";
    String d = " ";
    String e = " ";
    String f = " ";
    String g = " ";

    boolean fileExists = false;
    File newFile = null;
    while(!fileExists) 
    {
      System.out.println("Enter the name of the file you want to open: ");
      FileN = scan.nextLine();
      newFile = new File(FileN);
      fileExists = newFile.exists();
      if (!fileExists)

      {
        System.out.println(FileN + " not found...");
      }

    }
    try {
        Scanner scan2;
        scan = new Scanner(newFile);
    }
    catch(FileNotFoundException fnfe) {
      System.out.println("sorry but the file doesn't seem to exist");
    }


   //++++++++++++++=FILE READ=++++++++++++++++++++
    System.out.println("*FILE HAS BEEN LOCATED*");
    System.out.println("*File contains: \n");
    while(scan.hasNext()) 
    {
        a = scan.nextLine();
        b = scan.nextLine();
        c = scan.nextLine();
        d = scan.nextLine();
        e = scan.nextLine();
        f = scan.nextLine();
        g = scan.nextLine();
    }

      //+++++++++++++++ARRAYS FOR THE LINES+++++++++++++++++++

    //~~~~A-LINE~~~~//
    String[] aline;

    aline = a.split(":");

    for (int i=0; i<aline.length; i++)
    {
        aline[i] = aline[i].trim();
        //System.out.println(aline[i]);
    }

    //~~~~B-LINE~~~~//

    String[] bline;
    bline = b.split(":");

    for (int i=0; i<bline.length; i++)
    {
        bline[i] = bline[i].trim();
        //System.out.println(bline[i]);
    }

    //~~~~C-LINE~~~~//

    String[] cline;
    cline = c.split(":");

    for (int i=0; i<cline.length; i++)
    {
        cline[i] = cline[i].trim();
        //System.out.println(cline[i]);
    }

    //~~~~D-LINE~~~~//

    String[] dline;
    dline = d.split(":");

    for (int i=0; i<dline.length; i++)
    {
        dline[i] = dline[i].trim();
        //System.out.println(dline[i]);
    }

    //~~~~e-LINE~~~~//

    String[] eline;
    eline = e.split(":");

    for (int i=0; i<eline.length; i++)
    {
        eline[i] = eline[i].trim();
        //System.out.println(eline[i]);
    }

    //~~~~f-LINE~~~~//

    String[] fline;
    fline = f.split(":");

    for (int i=0; i<fline.length; i++)
    {
        fline[i] = fline[i].trim();
        //System.out.println(fline[i]);
    }

    //~~~~g-LINE~~~~//

    String[] gline;
    gline = g.split(":");

    for (int i=0; i<gline.length; i++)
    {
        gline[i] = gline[i].trim();
        //System.out.println(gline[i]);
    }

    String user       =    aline    [0];
    //~~~~~~~~~GAME NAMES~~~~~~~~~~~~~//

    //GTA
    String gameone    =    bline    [0];

    //MINECRAFT
    String gametwo  =    cline  [0];

    //ASSASSIN'S CREED IV
    String gamethree   =    dline   [0];

    //PAYDAY2
    String gamefour   =    eline    [0];

    //WOLFENSTEIN 
    String gamefive   =    fline    [0];

    //FARCRY 4
    String gamesix  =    gline  [0];




    //~~~~~~~~~~Achievement Score~~~~~~~~~~~~//


    //GTA SCORE
    String scoreone     =    bline  [1];

    //MINECRAFT SCORE
    String scoretwo     =    cline  [1];

    //ASSASSIN'S CREED IV SCORE
    String scorethree   =    dline  [1];

    //PAYDAY2 SCORE
    String scorefour    =    eline  [1];

    //WOLFENSTEIN SCORE
    String scorefive    =    fline  [1];

    //FARCRY 4 SCORE
    String scoresix     =    gline  [1];

//+++++++++++++++++++++TOTAL~~CALC++++++++++++++++++++++//
    double totalcount = 79.566; // change to the amount played.
    int totalhours = (int)totalcount;
    int totalmin = (int)(totalcount*60)%60;
    int totalsec = (int)(totalcount*(60*60))%60;
    System.out.println("TOTAL TIME PLAYED:");
    System.out.println(String.format("%s(hours) %s(minutes) %s(seconds)", 
    totalhours, totalmin, totalsec));       

     //~~~~~~~~~~Minutes Played~~~~~~~~~~~~//

    //GTA min
    String minone     =    bline    [2];

    //MINECRAFT min
    String mintwo     =    cline    [2];

    //ASSASSIN'S CREED IV min
    String minthree   =    dline    [2];

    //PAYDAY2 min
    String minfour    =    eline    [2];

    //WOLFENSTEIN min
    String minfive    =    fline    [2];

    //FARCRY 4 min
    String minsix     =    gline    [2];

    //~~~~~~~~~GAMES TEST~~~~~~~~~~~~//     

            System.out.println("\nUSER: "+user);
            System.out.println("\nDATA: ");
            System.out.println("1: "+gameone+"       | score: "+scoreone+"  
            | minutes played: "+minone);
            System.out.println("2: "+gametwo+"       | score:  "+scoretwo+" 
             | minutes played: "+mintwo);
            System.out.println("3: "+gamethree+"     | score: "+scorethree+"    
           | minutes played: "+minthree);
            System.out.println("4: "+gamefour+"          | score: 
            "+scorefour+"   | minutes played: "+minfour);
            System.out.println("5: "+gamefive+"      | score: "+scorefive+" 
           | minutes played: "+minfive);
            System.out.println("6: "+gamesix+"       | score: "+scoresix+"  
           | minutes played: "+minsix);

            if (bline.length < 3)
            {
                int column = 0;
                for(int i = 0; i<bline.length; i++){
                    column = i;
                    if(bline[i] == null || bline[i].trim() == ""){
                        System.out.println("There is an error in row two 
                  column "+(i+1));
                    }
                }
             }



}


 }

【问题讨论】:

    标签: java arrays string validation


    【解决方案1】:
    if (bline.length < 3)
    {
        int column = 0;
        for(int i = 0; i<bline.length; i++){
            column = i;
            if(bline[i] == null || bline[i].trim() == ""){
                System.out.println("There is an error in row two column "+(i+1));
            }
        }
     }
    

    没有测试,但应该可以工作

    编辑:

    查看您的完整代码bline[2], cline[2]... 等等,如果文件中首先缺少这些值,则会给您一个 Index Out of bounds 异常,因此在进行该调用之前,您应该先进行检查,您可以创建一个做检查的静态方法

    public static String getAtIndex(String[] array, int indexToCkeck){
        if(indexToCkeck >=array.length){
            return "";
        }
        else{
            return array[indexToCkeck];
        }
    }
    

    所以不要使用bline[2], cline[2] ...,而是使用readfile.getAtIndex(bline, 2),这样如果信息丢失,它将返回一个空字符串

    也没有测试,不过应该没问题

    【讨论】:

    • 这会很好用,但是现在当我从 .txt 文件中的 bline 数组中删除数据时,我收到一个 ArrayIndexOutOfBoundsException 我该如何解决这个问题?
    • 我认为你应该发布完整的代码。考虑到您对数组的数量进行了硬编码,您自然会得到超出范围的索引
    【解决方案2】:

    使用经过良好测试的库,例如 supercsvany other。一旦您的文本格式变得更复杂,这将为您节省一些时间。它还提供了一组很好的内置数据类型,用于验证数据的每一列。您还可以将数据直接映射到 POJO,这在某些情况下很方便。

    要将每一行加载到地图中,您可以执行以下操作:

    在 stack47220687.txt 中准备您的文件:

    Gamename: Gamescore: Minutestoplay
    Gameone : 120 : 1428 
    Gametwo : 20 : 10 
    Gamethree : 90 : 800 
    Gamefour : 190 : 2001 
    Gamefive : 25 : 80 
    Gamesix : 55 : 862
    

    并使用类似的东西

    package stack47220687;
    
    import java.io.FileReader;
    import java.util.Map;
    
    import org.junit.Test;
    import org.supercsv.cellprocessor.constraint.NotNull;
    import org.supercsv.cellprocessor.ift.CellProcessor;
    import org.supercsv.io.CsvMapReader;
    import org.supercsv.io.ICsvMapReader;
    import org.supercsv.prefs.CsvPreference;
    
    public class HowToReadACSVFile {
    
    private static final CsvPreference COLON_DELIMITED = new CsvPreference.Builder('"', ':', "\n").build();
    
    private static CellProcessor[] getProcessors() {
        final CellProcessor[] processors = new CellProcessor[] { new NotNull(), // gamename
                        new NotNull(), // gamescore
                        new NotNull(), // minutestoplay
        };
        return processors;
    }
    
    @Test
    public void read() throws Exception {
        ICsvMapReader mapReader = null;
        try {
            mapReader = new CsvMapReader(new FileReader(
                            Thread.currentThread().getContextClassLoader().getResource("stack47220687.txt").getPath()),
                            COLON_DELIMITED);
    
            // the header columns are used as the keys to the Map
            final String[] header = mapReader.getHeader(true);
            final CellProcessor[] processors = getProcessors();
    
            Map<String, Object> oneRecordInAMap;
            while ((oneRecordInAMap = mapReader.read(header, processors)) != null) {
                System.out.println(String.format("lineNo=%s, rowNo=%s, this line stored in a map=%s",
                                mapReader.getLineNumber(), mapReader.getRowNumber(), oneRecordInAMap));
                /**
                 * oneRecordInAMap.get("Gamescore");
                 */
    
            }
    
        } finally {
            if (mapReader != null) {
                mapReader.close();
            }
        }
    }
    
    }
    

    适用于超级 csv 2.4.0

    <dependency>
            <groupId>net.sf.supercsv</groupId>
            <artifactId>super-csv</artifactId>
            <version>2.4.0</version>
        </dependency>
    

    会打印出来

    lineNo=2, rowNo=2, this line stored in a map={ Gamescore= 120 , Gamename=Gameone ,  Minutestoplay= 1428 }
    lineNo=3, rowNo=3, this line stored in a map={ Gamescore= 20 , Gamename=Gametwo ,  Minutestoplay= 10 }
    lineNo=4, rowNo=4, this line stored in a map={ Gamescore= 90 , Gamename=Gamethree ,  Minutestoplay= 800 }
    lineNo=5, rowNo=5, this line stored in a map={ Gamescore= 190 , Gamename=Gamefour ,  Minutestoplay= 2001 }
    lineNo=6, rowNo=6, this line stored in a map={ Gamescore= 25 , Gamename=Gamefive ,  Minutestoplay= 80 }
    lineNo=7, rowNo=7, this line stored in a map={ Gamescore= 55 , Gamename=Gamesix ,  Minutestoplay= 862}
    

    如果您的格式不正确,它还会提供有意义的错误消息。

    【讨论】:

    • 感谢您的建议,但是文件类型将特别是 .txt 文件,因此我将无法使用 super-csv,因为在阅读了他们的网站后,您似乎无法使用使用该特定库打开 txt 文件。
    • 嗨,我提供了一些应该指向正确方向的示例代码。
    • 当然可以用它读取txt文件。 A CSV in fact is a plain text file。多亏了现有的工具,如果处理类似表格的结构,它也是一种非常方便的格式。
    • 感谢您向我介绍 Super-CSV,我已经实现了您建议的代码,并且运行良好!
    猜你喜欢
    • 1970-01-01
    • 2018-12-04
    • 2013-01-09
    • 2015-10-29
    • 2014-11-23
    • 2018-05-16
    • 1970-01-01
    • 2019-12-19
    • 1970-01-01
    相关资源
    最近更新 更多