Як сартаваць імёны файлаў у парадку ўзрастання?

У мяне ёсць набор файлаў у тэчцы, і ўсе яны, пачынаючы з падобнай назвай, за выключэннем аднаго. Вось прыклад:

Coordinate.txt
Spectrum_1.txt
Spectrum_2.txt
Spectrum_3.txt
.
.
.
Spectrum_11235

Я магу пералічыць усе файлы з названай тэчкі, але спіс не ў парадку ўзрастання колькасці спектру. Прыклад: Я атрымліваю наступны вынік, калі праграма выконваецца:

Spectrum_999.txt
Spectrum_9990.txt
Spectrum_9991.txt
Spectrum_9992.txt
Spectrum_9993.txt
Spectrum_9994.txt
Spectrum_9995.txt
Spectrum_9996.txt
Spectrum_9997.txt
Spectrum_9998.txt
Spectrum_9999.txt

Але гэты парадак не з'яўляецца правільным. Там павінна быць Spectrum_1000.txt файл пасля Spectrum_999.txt. Можа хто-небудзь дапамагчы? Вось код:

import java.io.*;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

    public class FileInput {

        public void userInput()
        {
            Scanner scanner = new Scanner( System.in );
            System.out.println("Enter the file path: ");
            String dirPath = scanner.nextLine();//Takes the directory path as the user input

            File folder = new File(dirPath);
            if(folder.isDirectory())
            {
                File[] fileList = folder.listFiles();

                Arrays.sort(fileList);

                System.out.println("\nTotal number of items present in the directory: " + fileList.length );


               //Lists only files since we have applied file filter
                for(File file:fileList)
                {
                    System.out.println(file.getName());
                }

               //Creating a filter to return only files.
                FileFilter fileFilter = new FileFilter()
                {
                    @Override
                    public boolean accept(File file) {
                        return !file.isDirectory();
                    }
                };

                fileList = folder.listFiles(fileFilter);

               //Sort files by name
                Arrays.sort(fileList, new Comparator()
                {
                    @Override
                    public int compare(Object f1, Object f2) {
                        return ((File) f1).getName().compareTo(((File) f2).getName());
                    }
                });

                //Prints the files in file name ascending order
                for(File file:fileList)
                {
                    System.out.println(file.getName());
                }

            }   
        }
    }
16

8 адказы

Тое, што вы просіце за гэта лікавы сартавання. Вам неабходна рэалізаваць кампаратар і перадаць яго Масівы # сартаваць метад. У метадзе параўнання трэба атрымаць лік з кожнага файла затым параўнаць лічбы.

The reason why you get the output you are getting now is that sorting happens alphanumerically

Here a is a very basic way of doing it. This code uses simple String-operation to extract the numbers. This works if you know the format of the filename, in your case Spectrum_.txt. A better way of doing the extraction is to use regular expression.

public class FileNameNumericSort {

    private final static File[] files = {
        new File("Spectrum_1.txt"),
        new File("Spectrum_14.txt"),
        new File("Spectrum_2.txt"),
        new File("Spectrum_7.txt"),     
        new File("Spectrum_1000.txt"), 
        new File("Spectrum_999.txt"), 
        new File("Spectrum_9990.txt"), 
        new File("Spectrum_9991.txt"), 
    };

    @Test
    public void sortByNumber() {
        Arrays.sort(files, new Comparator() {
            @Override
            public int compare(File o1, File o2) {
                int n1 = extractNumber(o1.getName());
                int n2 = extractNumber(o2.getName());
                return n1 - n2;
            }

            private int extractNumber(String name) {
                int i = 0;
                try {
                    int s = name.indexOf('_')+1;
                    int e = name.lastIndexOf('.');
                    String number = name.substring(s, e);
                    i = Integer.parseInt(number);
                } catch(Exception e) {
                    i = 0;//if filename does not match the format
                          //then default to 0
                }
                return i;
            }
        });

        for(File f : files) {
            System.out.println(f.getName());
        }
    }
}

<�Моцны> Выхад

Spectrum_1.txt
Spectrum_2.txt
Spectrum_7.txt
Spectrum_14.txt
Spectrum_999.txt
Spectrum_1000.txt
Spectrum_9990.txt
Spectrum_9991.txt
28
дададзена
<�Я> «Адказы тут не прызначаныя, каб забяспечыць цалкам працоўны код якасці прадукцыі» </я> - Ну, гэта адзін са спосабаў пакласці яго. Іншае: Гэта проста няправільна, улічваючы патрабаванні Ора, і гэта было б лёгка атрымаць правільны :-)
дададзена аўтар Lukas Eder, крыніца
Як гэта атрымаць так шмат upvotes? Ён не ў стане выканаць сартаванне спісу ўводу ад пытання правільна, які ўключае ў сябе файлы, якія не прыстаўка такім жа чынам, напрыклад, <�Код> Coordinate.txt
дададзена аўтар Lukas Eder, крыніца
@LukasEder Вось вельмі просты спосаб зрабіць гэта. Гэты код выкарыстоўвае простыя радкі-аперацыю для здабывання нумары. Гэта працуе, калі вы ведаеце, фармат файла, у вашым выпадку Spectrum_ <�нумар> .txt. Лепшы спосаб зрабіць экстракцыю выкарыстоўваць рэгулярны выраз. Адказы тут не прызначаныя, каб забяспечыць цалкам працоўны код якасці прадукцыі, а не якія забяспечваюць намёкі парады аб тым, як вырашыць гэтую праблему, і ў канчатковым выніку вельмі просты код ўзор. Я спадзяюся, што я мог бы адказаць на ваша пытанне.
дададзена аўтар A4L, крыніца

прыняты ў цяперашні час адказу робіць гэта толькі для лікавых суфіксаў файлаў, якія заўсёды называюць тым жа імя (г.зн. ігнараваннем прэфікса).

A much more generic solution, which I blogged about here, works with any file name, splitting names in segments and ordering the segments numerically (if both segments are numbers) or lexicographically, otherwise. Idea inspired from this answer:

public final class FilenameComparator implements Comparator {
    private static final Pattern NUMBERS = 
        Pattern.compile("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
    @Override public final int compare(String o1, String o2) {
       //Optional "NULLS LAST" semantics:
        if (o1 == null || o2 == null)
            return o1 == null ? o2 == null ? 0 : -1 : 1;

       //Splitting both input strings by the above patterns
        String[] split1 = NUMBERS.split(o1);
        String[] split2 = NUMBERS.split(o2);
        for (int i = 0; i < Math.min(split1.length, split2.length); i++) {
            char c1 = split1[i].charAt(0);
            char c2 = split2[i].charAt(0);
            int cmp = 0;

           //If both segments start with a digit, sort them numerically using 
           //BigInteger to stay safe
            if (c1 >= '0' && c1 <= '9' && c2 >= 0 && c2 <= '9')
                cmp = new BigInteger(split1[i]).compareTo(new BigInteger(split2[i]));

           //If we haven't sorted numerically before, or if numeric sorting yielded 
           //equality (e.g 007 and 7) then sort lexicographically
            if (cmp == 0)
                cmp = split1[i].compareTo(split2[i]);

           //Abort once some prefix has unequal ordering
            if (cmp != 0)
                return cmp;
        }

       //If we reach this, then both strings have equally ordered prefixes, but 
       //maybe one string is longer than the other (i.e. has more segments)
        return split1.length - split2.length;
    }
}

This can also handle version with subversions, e.g. things like version-1.2.3.txt

4
дададзена
@ A4L: Вы маеце рацыю, я залічаны мой крыніца, як я павінен!
дададзена аўтар Lukas Eder, крыніца
Я бачу, што вы з дапамогай рэгулярных выразаў, я задаюся пытаннем, дзе вы атрымалі натхненне ад ... я думаю, вы заслугоўваеце печыва ;-)
дададзена аўтар A4L, крыніца

Вы можаце знайсці рашэнне вашай праблемы ў каментарах вышэй, але, беручы пад увагу, што толькі спасылка была апублікаваная я даю код з гэтым сайтам. Працаваў вялікі.

  1. You need to create your own AlphanumericalComparator.

     import java.io.File;
     import java.util.Comparator;
    
    public class AlphanumFileComparator implements Comparator
    {
    
       private final boolean isDigit(char ch)
       {
        return ch >= 48 && ch <= 57;
       }
    
    
    private final String getChunk(String s, int slength, int marker)
    {
        StringBuilder chunk = new StringBuilder();
        char c = s.charAt(marker);
        chunk.append(c);
        marker++;
        if (isDigit(c))
        {
            while (marker < slength)
            {
                c = s.charAt(marker);
                if (!isDigit(c))
                    break;
                chunk.append(c);
                marker++;
            }
        } else
        {
            while (marker < slength)
            {
                c = s.charAt(marker);
                if (isDigit(c))
                    break;
                chunk.append(c);
                marker++;
            }
        }
        return chunk.toString();
    }
    
    public int compare(Object o1, Object o2)
    {
        if (!(o1 instanceof File) || !(o2 instanceof File))
        {
            return 0;
        }
        File f1 = (File)o1;
        File f2 = (File)o2;
        String s1 = f1.getName();
        String s2 = f2.getName();
    
        int thisMarker = 0;
        int thatMarker = 0;
        int s1Length = s1.length();
        int s2Length = s2.length();
    
        while (thisMarker < s1Length && thatMarker < s2Length)
        {
            String thisChunk = getChunk(s1, s1Length, thisMarker);
            thisMarker += thisChunk.length();
    
            String thatChunk = getChunk(s2, s2Length, thatMarker);
            thatMarker += thatChunk.length();
    
            /** If both chunks contain numeric characters, sort them numerically **/
    
            int result = 0;
            if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))
            {
               //Simple chunk comparison by length.
                int thisChunkLength = thisChunk.length();
                result = thisChunkLength - thatChunk.length();
               //If equal, the first different number counts
                if (result == 0)
                {
                    for (int i = 0; i < thisChunkLength; i++)
                    {
                        result = thisChunk.charAt(i) - thatChunk.charAt(i);
                        if (result != 0)
                        {
                            return result;
                        }
                    }
                }
            } else
            {
                result = thisChunk.compareTo(thatChunk);
            }
    
            if (result != 0)
                return result;
        }
    
        return s1Length - s2Length;
    }
    }
    

<�Моцны> 2. Сартаваць файлы, у залежнасці ад гэтага класа.

     File[] listOfFiles = rootFolder.listFiles();
     Arrays.sort(listOfFiles, new AlphanumFileComparator() );
     ...to sth with your files.

Спадзяюся, што гэта дапамагае. Ён працаваў для мяне, як шарм.

Solution from: http://www.davekoelle.com/files/AlphanumComparator.java here

2
дададзена

Вы можаце выкарыстоўваць Collections.sort (FileList); сартаваць ArrayList.

затым выкарыстоўвайце

 for(File file:fileList)                
         System.out.println(file.getName());

Collections.sort()

1
дададзена
У чым праблема з гэтым
дададзена аўтар PSR, крыніца
праверыць адказ ніжэй я думаю, што гэта будзе працаваць для і
дададзена аўтар PSR, крыніца
кі пачакайце 2 хвіліны я дам
дададзена аўтар PSR, крыніца
затым выкарыстоўваць падрадок і змясціць іх у спіс
дададзена аўтар PSR, крыніца
Затым выкарыстоўвайце Arrays.sort
дададзена аўтар PSR, крыніца
Вы просіце масіў я маю рацыю
дададзена аўтар PSR, крыніца
Ці можаце вы дапамагчы мне ў гэтым? Дзякуй
дададзена аўтар novicegeek, крыніца
Так. Але праблема ўсё яшчэ не вырашана. Я хачу, што лічбы ў імёнах файлаў павінны быць размешчаны ў парадку ўзрастання, а не лістынг на намаляваны вышэй.
дададзена аўтар novicegeek, крыніца
Я выдаліў код Arrays.sort (FileList, новы кампаратар() {@Override грамадскага ИНТ параўнання (f1 аб'екта, f2 Object) {вяртанне ((File) f1) .getName (). CompareTo (((File) f2 ) .getName ());}}); і паспрабаваў Collections.sort (FileList); , але наступнае паведамленне пра памылку паказана ніжэй: Спосаб сартавання (List ) ў калекцыях тыпу не ўжываецца для аргументаў (File []) Як дзейнічаць?
дададзена аўтар novicegeek, крыніца
Я паспрабаваў гэта, але Collections.sort (FileList); адлюстроўваецца наступнае паведамленне пра памылку: Метад сартавання (List ) у калекцыях тыпу не ўжываецца для аргументаў (File [])
дададзена аўтар novicegeek, крыніца

Яшчэ адзін спосаб зрабіць гэта, але, выкарыстоўваючы сілу java8

List x = Files.list(Paths.get("C:\\myPath\\Tools"))
            .filter(p -> Files.exists(p))
            .map(s -> s.getFileName())
            .sorted()
            .collect(Collectors.toList());

x.forEach(System.out::println);
1
дададзена
калі вы выкарыстоўваеце адлюстраванне, сартуе і ўсё пасля таго, як будзе падавацца з імем (= аб'ект String), а не фактычным шляхам або файлам аб'ектам. На зборы вынік, ToList будзе фактычна генераваць List , а не List аб'ект. Я адаптаваць свой код, хоць, каб адпавядаць маім патрэбам: Файл [] sortedFiles = Arrays.stream (файлы) .filter (F -> Files.exists (f.toPath ())) сартуюцца (Comparator.comparing (. файл :: & ZWNJ; GetName)) ToArray (Fi & ZWNJ ;. ле [] :: новый);
дададзена аўтар Roman Vottner, крыніца

<�Код> NameFileComparator клас даступны ў бібліятэцы Commons IO, якія маюць функцыю сартавання масіва файлаў па імені, даце апошняга змены, памер і многія more.Files могуць быць адсартаваныя ў парадку ўзрастання і змяншэння, з адчувальнасцю да рэгістра або неадчувальнасці да рэгістра ,

імпарт:

<�Код> org.apache.commons.io.comparator.NameFileComparator

код:

File directory = new File(".");
File[] files = directory.listFiles();
Arrays.sort(files, NameFileComparator.NAME_COMPARATOR)
1
дададзена
Гэта не сартуе шлях ОП хоча. Яна ігнаруе лічбы.
дададзена аўтар c4k, крыніца
Arrays.sort(fileList, new Comparator()
{
    @Override
    public int compare(Object f1, Object f2) {
        String fileName1 = ((File) f1).getName();
        String fileName2 = ((File) f1).getName();

        int fileId1 = Integer.parseInt(fileName1.split("_")[1]);
        int fileId2 = Integer.parseInt(fileName2.split("_")[1]);

        return fileId1 - fileId2;
    }
});

пераканайцеся, што для працы з файламі, якія не мае _ ў імя

1
дададзена

Проста выкарыстоўвайце:

  1. Для ўзрастанні: Collections.sort (Спіс)

  2. Для змяншэнні: Collections.sort (Спіс, Collections.reverseOrder ())

1
дададзена
<�Б> Гэта павінна быць тыпу <�я> List
дададзена аўтар Somil Aseeja, крыніца