简体   繁体   中英

Run into Array index out of bounds Java on certain datetime format

I wrote a code to sort a document. The document consists of datetime data. Before I put my document to be sorted, I wrote a code to convert the datetime from Unix epoch time to regular date time. If I convert it to yyyy-MM-dd format like 2013-10-10, the sorting program can work perfectly. But it I convert it to E yyyy-MM-dd format like 2015-09-02 Wed, I always get a "Array Index out of Bounds error", which is weird considering I have put the right number for my array index. Now I am wondering why I got this error if I put the day name and everything is fine if I made it into regular datetime format (without day name). Is there any way I can solve this?

Here is the code I use to sort the data. I think it's a very terrible and not so efficient code (considering my data is pretty big, and it's actually a big data), but I can't think of anything better now and it still runs pretty well on my laptop (less than 10 seconds). But any suggestion is welcome. Thanks in advance.

public static void main(String[] args) {
    try {Scanner scanner = new Scanner(new File("file.txt"));

        int number = 1710680;
        String dataList[] = new String[number];
        int count = 0;

        while (scanner.hasNext()) {
            dataList[count] = String.valueOf(scanner.next());
            count++;
        }

        Arrays.sort(dataList);


        try (FileWriter file = new FileWriter("file.txt)) {
            String newLine = System.getProperty("line.separator");

            //read the header first, so it won't be processed in the looping
            for(String data : dataList){
                file.write(data+newLine);
            }
            System.out.println("Done now");
            System.out.println("Check your file");
        }catch(Exception e){
            System.out.println("Failed here -> "+e.getMessage());

            System.err.println(e);
        }


    } catch (Exception e) {
        System.out.println("Failed -> " + e.getMessage());

        System.err.println(e);
    }

}

I think I just realized the the obvious: the problem is between the definition of the format of your file and your parser for the file.

If I understand correctly, you have a separate program, not shown, that takes numbers (Unix timestamps), formats the timestamps as text and writes them to the file 'file.txt'. Then you have the program, shown, that attempts to sort the text in the file.

You are using Scanner to parse the file into separate tokens which will then be sorted. Read the documentation closely to determine if it is suitable for your data:

A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.

When the file contents look like:

2015-01-01 2015-10-02 2015-02-05
2014-12-21 2013-03-08

Then you will get 5 tokens from your Scanner .

However, when the file contents look like

2015-01-01 Wed 2015-10-02 Mon 2015-02-05 Thu
2014-12-21 Sun 2013-03-08 Sat

Then you will get 10 tokens from your Scanner . This is why you get an ArrayIndexOutOfBounds exception: you have twice as many tokens as you allocated space in your array.

If your file contents look like this:

2015-01-01 Wed
2015-10-02 Mon
2015-02-05 Thu
2014-12-21 Sun
2013-03-08 Sat

Then use a BufferedReader and read the data with readLine() , or simply use the existing sort program.

Better yet, in your program that is formatting the timestamps as text just sort the timestamps first.

Consider using java 8 streams and string to date conversion:

public static void main(String[] args) throws IOException {
    DateFormat inFormat = new SimpleDateFormat("yyyy-M-dd", Locale.ENGLISH);
    DateFormat outFormat  = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
    Path input = Paths.get("file.txt");
    Path output = Paths.get("outfile.txt");
    List<String> dataList = Files
        .readAllLines(input) //list of strings
        .stream() //java 8 stream
        .map(string -> {
            try {
                return inFormat.parse(string);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }) //strings converted to dates
        .filter(date -> date != null) //filtered non null dates
        .sorted()
        .map(outFormat::format) //dates converted to strings
        .collect(Collectors.toList()); //Stream<String> collected to List<String>


    if( dataList.size() > 0) {
        //write all lines
        Files.write(output, dataList, Charset.defaultCharset(), StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);
    }

    System.out.println("Done now");
    System.out.println("Check your file");

}

Or simple imperative version with date parsing:

public static void main(String[] args) throws IOException {
    DateFormat inFormat = new SimpleDateFormat("yyyy-M-dd", Locale.ENGLISH);
    DateFormat outFormat  = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);

    Path input = Paths.get("file.txt");

    List<Date> dateList = new ArrayList<>();

    for( String string: Files.readAllLines(input)) {
        try {
            dateList.add(inFormat.parse(string));
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
    dateList.sort(Date::compareTo);
    FileWriter outfile = new FileWriter("file.txt");
    for(Date date: dateList) {
        outfile.write(outFormat.format(date));
    }

    System.out.println("Done now");
    System.out.println("Check your file");

}

Notice - You can read all lines from file to list using:

Files.readAllLines(input)

and use Lists with dynamic size instead of arrays

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM