2016-01-22 6 views
1

Предположим, у меня есть относительно большой файл (около 100 МБ), который я хочу для многоадресной рассылки всем членам кластера. Как отправить файл в куски с помощью jgroups (желательно с демонстрацией кода)? Файл следует читать в кусках со стороны приемников. Также как я могу гарантировать, что порядок последовательности кусков поддерживается на стороне приемников.Как многоадресные файлы в jgroups

EDIT 1 Вот что я пробовал до сих пор. Я просто отправить файл в целом и записи его содержимого на стороне получателя во временный файл

public class SimpleFileTransfer extends ReceiverAdapter { 

    JChannel channel; 

    private void start() throws Exception{ 
     channel = new JChannel(); 
     channel.setReceiver(this); 
     channel.connect("FileCluster"); 
//  channel.getState(null, 10000); 
     File file = new File("/res/test.txt"); //the file to be sent 
     eventLoop(file); 
     channel.close(); 
    } 

    private void eventLoop(File file) throws IOException{ 
     BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file))); 
     try { 
      Message msg = new Message(null, null, in); 
      channel.send(msg); 
     } 
     catch (Exception e){ 
      e.printStackTrace(); 
     } 
    } 


    public void receive(Message msg) 
    { 
     try { 
      File temp = new File("/res/temp.txt"); 
      FileWriter writer = new FileWriter(temp); 
      InputStream in = new ByteArrayInputStream(msg.getBuffer()); 
      int next = in.read(); 
      while (next != -1){ 
       writer.write(next); 
       next = in.read(); 
      } 
     } 
     catch (IOException ie) 
     { 
      ie.printStackTrace(); 
     } 


    } 

} 
+0

Это не сайт, где люди пишут код для вас. Покажите, что вы уже пробовали, тогда люди помогут вам. Downvoting. –

+0

@ Мы - Борг, достаточно справедливы. Я уточнил вопрос с тем, что я пробовал до сих пор. – avidProgrammer

+0

@WeareBorg Я думаю, что вы сделали свою мысль, вам не нужно было опускать довольно хороший вопрос. – kimathie

ответ

3

Ниже это лучший вариант, который Куски до больших файлов на куски 8K. Файл X записывается в/tmp/X. Обратите внимание, что /home/bela/fast.xml конфигурация должна быть изменена, конечно:

public class SimpleFileTransfer extends ReceiverAdapter { 
protected String filename; 
protected JChannel channel; 
protected Map<String,OutputStream> files=new ConcurrentHashMap<>(); 
protected static final short ID=3500; 

private void start(String name, String filename) throws Exception { 
    ClassConfigurator.add((short)3500, FileHeader.class); 
    this.filename=filename; 
    channel=new JChannel("/home/bela/fast.xml").name(name); 
    channel.setReceiver(this); 
    channel.connect("FileCluster"); 
    eventLoop(); 
} 

private void eventLoop() throws Exception { 
    while(true) { 
     Util.keyPress(String.format("<enter to send %s>\n", filename)); 
     sendFile(); 
    } 
} 

protected void sendFile() throws Exception { 
    FileInputStream in=new FileInputStream(filename); 
    try { 
     for(;;) { 
      byte[] buf=new byte[8096]; 
      int bytes=in.read(buf); 
      if(bytes == -1) 
       break; 
      sendMessage(buf, 0, bytes, false); 
     } 
    } 
    catch(Exception e) { 
     e.printStackTrace(); 
    } 
    finally { 
     sendMessage(null, 0, 0, true); 
    } 
} 


public void receive(Message msg) { 
    byte[] buf=msg.getRawBuffer(); 
    FileHeader hdr=(FileHeader)msg.getHeader(ID); 
    if(hdr == null) 
     return; 
    OutputStream out=files.get(hdr.filename); 
    try { 
     if(out == null) { 
      File tmp=new File(hdr.filename); 
      String fname=tmp.getName(); 
      fname="/tmp/" + fname; 
      out=new FileOutputStream(fname); 
      files.put(hdr.filename, out); 
     } 
     if(hdr.eof) { 
      Util.close(files.remove(hdr.filename)); 
     } 
     else { 
      out.write(msg.getRawBuffer(), msg.getOffset(), msg.getLength()); 
     } 
    } 
    catch(Throwable t) { 
     System.err.println(t); 
    } 
} 


protected void sendMessage(byte[] buf, int offset, int length, boolean eof) throws Exception { 
    Message msg=new Message(null, buf, offset, length).putHeader(ID, new FileHeader(filename, eof)); 
    // set this if the sender doesn't want to receive the file 
    // msg.setTransientFlag(Message.TransientFlag.DONT_LOOPBACK); 
    channel.send(msg); 
} 

protected static class FileHeader extends Header { 
    protected String filename; 
    protected boolean eof; 

    public FileHeader() {} // for de-serialization 

    public FileHeader(String filename, boolean eof) { 
     this.filename=filename; 
     this.eof=eof; 
    } 

    public int size() { 
     return Util.size(filename) + Global.BYTE_SIZE; 
    } 

    public void writeTo(DataOutput out) throws Exception { 
     Util.writeObject(filename, out); 
     out.writeBoolean(eof); 
    } 

    public void readFrom(DataInput in) throws Exception { 
     filename=(String)Util.readObject(in); 
     eof=in.readBoolean(); 
    } 
} 

public static void main(String[] args) throws Exception { 
    if(args.length != 2) { 
     System.out.printf("%s <name> <filename>\n", SimpleFileTransfer.class.getSimpleName()); 
     return; 
    } 
    new SimpleFileTransfer().start(args[0], args[1]); // name and file 
} 

}

0

Никто не собирается писать код для вас, но: файл

  1. Turn в Byte массив
  2. Перерыв массив на куски
  3. Wrap каждый кусок в конверте, который говорит, какую часть он
  4. Отправить куски
  5. Прочтите конверт Верните их снова вместе

Ни одна из этих вещей не очень индивидуальна.

+0

См. Обновление к моему вопросу – avidProgrammer

+0

Ваше обновление не имеет никакого значения для рекомендаций, которые я дал –

1

Ниже приводится неверное решение. Чтобы запустить его, для конфигурации необходимо, чтобы bundler_type = «отправитель-отправляет» (в UDP), и для приложения требуется достаточно памяти. Это решение плохо, потому что он считывает весь файл в буфер, который один раз повторяется в JGroups. Следующее решение, которое я опубликую, лучше, потому что он разбивает этот большой файл на несколько меньших кусков. Обратите внимание, что отправка большого файла, JGroups также выполняет внутреннюю разбивку (фрагментацию), но вам все равно нужно создать этот большой байт [] на уровне приложения, что плохо.

public class SimpleFileTransfer extends ReceiverAdapter { 
protected String filename; 
protected JChannel channel; 

private void start(String name, String filename) throws Exception { 
    this.filename=filename; 
    channel=new JChannel("/home/bela/fast.xml").name(name); 
    channel.setReceiver(this); 
    channel.connect("FileCluster"); 
    eventLoop(); 
    channel.close(); 
} 

private void eventLoop() throws Exception { 
    while(true) { 
     Util.keyPress(String.format("<enter to send %s>\n", filename)); 
     sendFile(); 
    } 
} 

protected void sendFile() throws Exception { 
    Buffer buffer=readFile(filename); 
    try { 
     Message msg=new Message(null, buffer); 
     channel.send(msg); 
    } 
    catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 


public void receive(Message msg) { 
    System.out.printf("received %s from %s\n", Util.printBytes(msg.getLength()), msg.src()); 
    try { 
     File temp=new File("/tmp/temp.txt"); 
     FileWriter writer=new FileWriter(temp); 
     InputStream in=new ByteArrayInputStream(msg.getBuffer()); 
     int next=in.read(); 
     while(next != -1) { 
      writer.write(next); 
      next=in.read(); 
     } 
    } 
    catch(IOException ie) { 
     ie.printStackTrace(); 
    } 
} 


protected static Buffer readFile(String filename) throws Exception { 
    File file=new File(filename); 
    int size=(int)file.length(); 
    FileInputStream input=new FileInputStream(file); 
    ByteArrayDataOutputStream out=new ByteArrayDataOutputStream(size); 
    byte[] read_buf=new byte[1024]; 
    int bytes; 
    while((bytes=input.read(read_buf)) != -1) 
     out.write(read_buf, 0, bytes); 
    return out.getBuffer(); 
} 


public static void main(String[] args) throws Exception { 
    if(args.length != 2) { 
     System.out.printf("%s <name> <filename>\n", SimpleFileTransfer.class.getSimpleName()); 
     return; 
    } 
    new SimpleFileTransfer().start(args[0], args[1]); // name and file 
} 

}