2016-07-31 2 views
2

Мне нужна ваша помощь. Я использую Talend ESB, и я хочу сделать java beans.Вырезать файл в нескольких файлах (Java)

К примеру, у меня есть этот плоский файл:

11886 1855 0000004309000 
11886 1855 0000057370000 
11886 1856 0000057374001  
11886 1856 0000057375000  

В моем примере я хочу 2 файла (сообщения), а фильтр «1855» и «1856» (это количество заказов).

Первый файл:

11886 1855 0000004309000 
11886 1855 0000057370000 

Второй файл:

11886 1856 0000057374001  
11886 1856 0000057375000 

EDIT: Но я не знаю, количество заказов на один файл.

Если у меня есть три порядка (три строки каждый) в моем исходном файле ==> Я хочу три файла с 3 строками каждого заказа.

Если у меня есть четыре заказа в моем исходном файле ==> Я хочу четыре файла.

Если у меня есть пять заказов в моем исходном файле ==> Я хочу пять файлов.

и так далее .......................


Это мой старт-код. Я хотел бы разделить на несколько файлов. Я действительно зациклился на том, как это сделать.

package beans; 

import java.io.BufferedReader; 
import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.util.HashMap; 
import java.util.LinkedHashMap; 
import java.util.Map; 
import org.apache.camel.*; 


public class bean_test implements Processor{ 

    private static final String ENDPOINT_NAME = "Endpoint"; 
    private static final String END_TAG_ENDPOINT_NAME = "endEndpoint"; 
    private static final int NUMERO_SITE_START_POSITION = 6; 
    private static final int NUMERO_SITE_END_POSITION = 11; 


    @Override 
    public void process(Exchange exchange) throws Exception { 

     ProducerTemplate producerTemplate = exchange.getContext().createProducerTemplate(); 
     String ropEndpoint = exchange.getIn().getHeader(ENDPOINT_NAME, String.class); 
     String endRopEndpoint = exchange.getIn().getHeader(END_TAG_ENDPOINT_NAME, String.class); 
     InputStream is = new ByteArrayInputStream(exchange.getIn().getBody(String.class).getBytes()); 
     aggregateBody(producerTemplate, is, ropEndpoint, endRopEndpoint, new HashMap<String, Object>(exchange.getIn().getHeaders())); 

    } 

    private void aggregateBody(ProducerTemplate producerTemplate, InputStream content, String ropEndPoint, String endRopEndpoint, Map<String, Object> headers){ 
     BufferedReader br = new BufferedReader(new InputStreamReader(content)); 
     String line; 
     Map<String, StringBuilder> articles = new LinkedHashMap<String, StringBuilder>(); 
     StringBuilder aggregateFile = new StringBuilder(); 
     try { 
      String lineId = null; 
      while((line = br.readLine()) != null){ 
      lineId = line.substring(NUMERO_SITE_START_POSITION, NUMERO_SITE_END_POSITION); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     finally{ 
      try { 
       if(br != null)br.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

Заранее спасибо.

Louisa.

EDIT: Мой новый код, но я не знаю, как вернуть файл.

package beans; 

import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.ByteArrayInputStream; 
import java.io.File; 
import java.io.FileWriter; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.Map; 
import java.util.Set; 
import java.util.TreeSet; 

import org.apache.camel.*; 


public class bean_test implements Processor{ 

    private static final String ENDPOINT = "aggregateEndpoint"; 
    private static final int NUMERO_SITE_START_POSITION = 46; 
    private static final int NUMERO_SITE_END_POSITION = 55; 


    @Override 
    public void process(Exchange exchange) throws Exception { 

     ProducerTemplate producerTemplate = exchange.getContext().createProducerTemplate(); 
     String endpoint = exchange.getIn().getHeader(ENDPOINT, String.class); 
     InputStream is = new ByteArrayInputStream(exchange.getIn().getBody(String.class).getBytes()); 
     aggregateBody(producerTemplate, is, endpoint, new HashMap<String, Object>(exchange.getIn().getHeaders())); 

    } 

    private void aggregateBody(ProducerTemplate producerTemplate, InputStream content, String endpoint, Map<String, Object> headers){ 
     BufferedReader br = new BufferedReader(new InputStreamReader(content)); 
     String line; 
     Set<String> order=new TreeSet<String>(); 

     try { 
      String lineId = null; 
      while((line = br.readLine()) != null){ 
       lineId = line.substring(NUMERO_SITE_START_POSITION, NUMERO_SITE_END_POSITION); 
       order.add(lineId); 
      } 

      for(int i=0;i<order.size();i++){ 
       String key = "file" + i; 
       File F = new File(key); 
       Iterator it = order.iterator(); 
       FileWriter fw = new FileWriter(F.getAbsoluteFile()); 
       BufferedWriter bw = new BufferedWriter(fw); 

       while((line = br.readLine()) != null){ 
        while(it.hasNext()){ 
         lineId = line.substring(NUMERO_SITE_START_POSITION, NUMERO_SITE_END_POSITION); 
         if (lineId.equals(it.next())) { 
          bw.write(line); 
         } 
        } 

       } 
      } 


     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     finally{ 
      try { 
       if(br != null)br.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
+0

Какова логика разделения файла? –

+0

Hello Boris, Логика основана на полях 1855 и 1856 (позиция 7-11 в моем файле). Он должен быть объединен в 1855 и 1856 годах (два файла). – Louisa

+0

Хорошо, просто сделайте это. 1) Откройте два файла. 2) 'stream()' строки из входного файла. 3) В зависимости от рассматриваемого поля, напишите строку в соответствующий файл. 4) Закройте файлы. –

ответ

1

Этот ответ действительно пользователем Ranx, from the Camel list, не мое собственное; но, я думаю, это стоит воспроизвести, потому что он изящный и поддерживает идиому Верблюда.

Концептуально, вы хотите сплит записи в файле. Затем для каждой записи вы хотите использовать какое-либо значение в , выберите конечный выходной файл. enter image description here

Верблюд конкретного решения, предложенного пользователем Ranx в списке Camel используется функция Camel: имя файла назначения может быть получена из значения в сообщении (которое было частью вашей спецификации).

enter image description here Вы разделены на запись, а затем распаковать строку в некоторый формат, вытаскивать нужное поле и установить его в заголовок, мобилизовывать его обратно в строку, и, наконец, запись в файл (добавляющий), используя заголовок значение в имени файла.

Это выражалось в сниппет:

from("file:/inbox") 
.split(body()) 
.unmarshal(dataFormat) 
.setHeader("fileName",simple("${body.identifier}")) 
.marshal(dataFormat) 
.to("file:/outbox/?fileName=${header.fileName}.txt&fileExist=Append") 

В качестве альтернативы, вы, вероятно, избежать маршалинг и демаршаллинг, и использовать простой процессор, который прочитал тело Струнный как есть, и установить заголовок, как указано выше. Это будет: enter image description here

+0

Waahhho это работает! Спасибо, ты очень мук: D! – Louisa

0

Многие, кажется, думают, что вы не должны делиться вашими файлами. Но если вам нужно это сделать, простое решение для чтения в вашем файле, которое я называю flatfile.txt ниже, и проверьте вторую запись каждой строки, чтобы увидеть, будет ли она 1855 или 1856. В каждом случае напишите вывод в соответствующий файл.

try { 
    File f1 = new File("f1855.txt"); 
    File f2 = new File("f1856.txt"); 

    if (!f1.exists()) { 
     f1.createNewFile(); 
    } 
    FileWriter fw1 = new FileWriter(f1.getAbsoluteFile()); 
    BufferedWriter bw1 = new BufferedWriter(fw1); 

    if (!f2.exists()) { 
     f2.createNewFile(); 
    } 
    FileWriter fw2 = new FileWriter(f2.getAbsoluteFile()); 
    BufferedWriter bw2 = new BufferedWriter(fw2); 

    String currLine; 
    BufferedReader br = new BufferedReader(new FileReader("flatfile.txt")); 

    while ((currLine = br.readLine()) != null) { 
     String[] parts = currLine.split(" "); 
     if (parts[1].equals("1855")) { 
      bw1.write(currLine); 
     } 
     else if (parts[1].equals("1856")) { 
      bw2.write(currLine); 
     } 
     else { 
      System.out.println("Found a line which did not match 1855 or 1856."); 
     } 
    } 
} catch (IOException e) { 
    e.printStackTrace(); 
} finally { 
    try { 
     if (br != null) br.close(); 
     if (bw1 != null) bw1.close(); 
     if (bw2 != null) bw2.close(); 
    } catch (IOException ex) { 
     ex.printStackTrace(); 
    } 
} 
+0

Спасибо Тим за ответ! Это сложнее, я блокирую Мой входной файл, код 1855 или 1856 не всегда одинаковый, это номер заказа, и я не знаю, сколько разных кодов я У меня есть файл 5, 6, 7. Извините, я оговорился :( – Louisa

+0

@Louisa Итак, вы готовы иметь произвольное количество выходных файлов для каждого номера заказа? Теперь я начинаю согласитесь, что ваш подход может быть неправильным. –

+0

Мне нужен один файл по заказу, но у меня может быть случайный порядок номеров в исходном файле. Я также думаю, m идет в неправильном направлении ... – Louisa