سؤال

أنا أعمل في مكتب صغير ، ولدي تطبيق ، ويقوم بإنشاء ملف نصي كبير يحتوي على 14000 سطر ؛

بعد كل توليد ، يجب أن أقوم بتصفيةه وهو ممل حقًا ؛

أريد أن أكتب تطبيقًا مع Java حتى أتمكن من التعامل معه في أقرب وقت ممكن.

الرجاء مساعدتي؛ لقد كتبت تطبيقًا مع الماسح الضوئي (بالطبع بمساعدة :)) لكنه ليس جيدًا لأنه كان بطيئًا جدًا ؛

على سبيل المثال ، إنه ملفي:

SET CELL:NAME=CELL:0,CELLID=3;
SET LSCID:NAME=LSC:0,NETITYPE=MDCS,T32=5,EACT=FILTER-NOFILTER-MINR-FILTER-NOFILTER,ENSUP=GV2&NCR,MINCELL=6,MSV=PFR,OVLHR=9500,OTHR=80,BVLH=TRUE,CELLID=3,BTLH=TRUE,MSLH=TRUE,EIHO=DISABLED,ENCHO=ENABLED,NARD=NAP_STLP,AMH=ENABLED(3)-ENABLED(6)-ENABLED(9)

وأريد هذا الإخراج (تصفية :)

CELLID :  3
ENSUP  :  GV2&NCR
ENCHO  :  ENABLED
MSLH   :  TRUE
------------------------
Count of CELLID : 2

ما هو الحل الأفضل والأسرع من الآخر؟

إنه رمز المصدر الخاص بي:

public static void main(String[] args) throws FileNotFoundException {
        Scanner scanner = new Scanner(new File("i:\\1\\2.txt"));
        scanner.useDelimiter(";|,");
        Pattern words = Pattern.compile("(CELLID=|ENSUP=|ENCHO=)");

        while (scanner.hasNextLine()) {
          String key = scanner.findInLine(words);

          while (key != null) {
            String value = scanner.next();
            if (key.equals("CELLID=")) 
              System.out.print("CELLID:" + value+"\n");
             //continue with else ifs for other keys
              else if (key.equals("ENSUP="))
            System.out.print("ENSUP:" + value+"\n");

            else if (key.equals("ENCHO="))
            System.out.print("ENCHO:" + value+"\n");
            key = scanner.findInLine(words);
          }
          scanner.nextLine();
        }

}

شكرا جزيلا لك حقا ...

هل كانت مفيدة؟

المحلول

نظرًا لأن الكود الخاص بك لديه مشكلات في الأداء ، فأنت تحتاج أولاً إلى العثور على رقبة الزجاجة. يمكنك ملف تعريفه مع Profiler المتاحة مع IDE التي تستخدمها.

ومع ذلك ، نظرًا لأن الكود الخاص بك ليس مرتفعًا في الحساب ولكن IO مكثف ، سواء في قراءة الملف والإخراج باستخدام system.out.print ، هذا هو المكان الذي أقترح عليك فيه تحسين التحسين في ملف IO.

.

استبدل خط الرمز هذا

Scanner scanner = new Scanner(new File("i:\\1\\2.txt"));

.

مع هذه الخطوط من الكود

File file = new File("i:\\1\\2.txt");
BufferedReader br = new BufferedReader( new FileReader(file)  );
Scanner scanner = new Scanner(br);

أخبرنا إذا كان هذا يساعد.

.

نظرًا لأن الحل السابق لم يساعد كثيرًا ، فقد قمت بإجراء المزيد من التغييرات لتحسين التعليمات البرمجية الخاصة بك. قد تضطر إلى تصحيح الأخطاء في التحليل إن وجدت. تمكنت من عرض إخراج تحليل 392832 في حوالي 5 ثوان. الحل الأصلي يستغرق أكثر من 50 ثانية.

chages كما يلي:

  1. استخدام StringTokenizer بدلاً من الماسح الضوئي
  2. استخدام BufferedReader لقراءة ملف
  3. استخدام StringBuilder إلى الإخراج العازلة

.

public class FileParse {

    private static final int FLUSH_LIMIT = 1024 * 1024;
    private static StringBuilder outputBuffer = new StringBuilder(
            FLUSH_LIMIT + 1024);
    private static final long countCellId;

    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();
        String fileName = "i:\\1\\2.txt";
        File file = new File(fileName);
        BufferedReader br = new BufferedReader(new FileReader(file));
        String line;
        while ((line = br.readLine()) != null) {
            StringTokenizer st = new StringTokenizer(line, ";|, ");
            while (st.hasMoreTokens()) {
                String token = st.nextToken();
                processToken(token);
            }
        }
        flushOutputBuffer();
        System.out.println("----------------------------");
        System.out.println("CELLID Count: " + countCellId);
        long end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));
    }

    private static void processToken(String token) {
        if (token.startsWith("CELLID=")) {
            String value = getTokenValue(token);
            outputBuffer.append("CELLID:").append(value).append("\n");
            countCellId++;
        } else if (token.startsWith("ENSUP=")) {
            String value = getTokenValue(token);
            outputBuffer.append("ENSUP:").append(value).append("\n");
        } else if (token.startsWith("ENCHO=")) {
            String value = getTokenValue(token);
            outputBuffer.append("ENCHO:").append(value).append("\n");
        }
        if (outputBuffer.length() > FLUSH_LIMIT) {
            flushOutputBuffer();
        }
    }

    private static String getTokenValue(String token) {
        int start = token.indexOf('=') + 1;
        int end = token.length();
        String value = token.substring(start, end);
        return value;
    }

    private static void flushOutputBuffer() {
        System.out.print(outputBuffer);
        outputBuffer = new StringBuilder(FLUSH_LIMIT + 1024);
    }

}

.

تحديث على ENSUP و MSLH:

بالنسبة لي ، يبدو أنك قمت بتبديل ENSUP و MSLH في بيان على النحو التالي. وبالتالي ترى قيمة "MSLH" لـ "entup" والعكس بالعكس.

} else if (token.startsWith("MSLH=")) {
    String value = getTokenValue(token);
    outputBuffer.append("ENSUP:").append(value).append("\n");
} else if (token.startsWith("ENSUP=")) {
    String value = getTokenValue(token);
    outputBuffer.append("MSLH:").append(value).append("\n");
}

نصائح أخرى

من المحتمل أن يكون التصفية النصية البسيطة أسهل في الكتابة في بيرل (اختياري لأنني كنت أستخدمه لسنوات) أو بيثون (ما أوصي به لأشخاص جدد لأنها لغة أكثر حداثة).

عدة حلول لمشكلة مماثلة باستخدام جافا الماسح الضوئي أو دفق treamizer تمت مناقشتها مؤخرًا هنا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top