[Resolvido]Verificar transferência completa do arquivo via FTPClient

Pessoal,
Estou desenvolvendo uma aplicação utilizando quartz que vai em um servidor e verifica se existe um arquivo, se existir a aplicação baixa o arquivo.

Esse processo ocorre a cada 20minutos a partir de 1hr da madrugada até as 4hrs.

Supondo que quando for 1:20 eu encontre o arquivo e baixe ele, mas o sistema do outro lado que estava escrevendo ainda não terminou, então, eu baixei um arquivo incompleto.

A última linha do arquivo é padrão. Então verificar se esse linha existe é uma opção. Mas não consegui fazer isso com stream.

Alguém tem alguma luz…

Segue o código.

Valeu.

import sun.net.ftp.FtpClient;
...

FtpClient client = new FtpClient();
				
try {
	System.out.println("Abrindo conexão FTP");
	String server = "xx.xxx.xx.x";


	client.openServer(server);
	client.login(user, passwd);
	client.binary();
	System.out.println(client.welcomeMsg);

	File dir = new File("\\temp\\ccta");
	dir.mkdir();


	for (int i = 0 ; i < EMPRESAS.length ; i++) {
				
		String filename = "zbnbhr004_EPRV_20101105.txt";
		//String filename = PREFIXO_NOME_ARQUIVO + EMPRESAS[i] + "_" +dataAtual + ".txt";
		
		
		
		try {
		
			InputStream is = client.get(filename);
			BufferedInputStream bis = new BufferedInputStream(is);
			
			
			File fl = new File(dir, filename);
			
			if(!fl.exists()) {
										
				OutputStream os = new FileOutputStream(fl);
				BufferedOutputStream bos = new BufferedOutputStream(os);
				
				byte[] buffer = new byte[1024];
				int readCount;
	
				System.out.println("Getting: " + filename);
								
				while( (readCount = bis.read(buffer)) > 0) {
				  bos.write(buffer, 0, readCount);
				}
				bos.flush();
				bos.close();
				
			}
	}					
}catch(FileNotFoundException fle) {
	System.out.println("Arquivo não encontrado. Nova tentativa em 10 minutos.");
	fle.printStackTrace();

}

Tem um exemplo de leitura de um arquivo na ordem inversa, você adaptar para no seu caso pegar somente a primeira linha lida (que na verdade será a última linha do arquivo) e fazer sua comparação, espero que sirva.

[code]import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;

public class Test {

public static void main(String... args) throws Exception {

    // Stub input. You need to gather it yourself from your sources.
    File file = new File("/file.txt");
    long length = file.length(); // Get it from HTTP request header using file upload API in question (Commons FileUpload?).
    String encoding = "UTF-8"; // Get it from HTTP request header using file upload API in question (Commons FileUpload?).
    InputStream content = new FileInputStream(file); // Get it from HTTP request body using file upload API in question (Commons FileUpload?).

    // Now the real job.
    Reader input = new InputStreamReader(content, encoding);
    RandomAccessFile output = new RandomAccessFile(new File("/filereversed.txt"), "rwd");
    CharsetEncoder encoder = Charset.forName(encoding).newEncoder();

    for (int data; (data = input.read()) != -1;) {
        ByteBuffer bytes = encoder.encode(CharBuffer.wrap(new char[] { (char) data }));
        length -= bytes.limit();
        output.seek(length);
        output.write(bytes.array());
    }

    // Should actually be done in finally.
    input.close();
    output.close();
}

}
[/code]

Postando como resolvi meu problema…

Crio um novo File passando o diretório e o nome do arquivo, verifico se ele existe, se já existir, não inicio uma nova transferência dos dados e encerro o processamento.

Caso não exista, leio o stream e escrevo através de um Writer. Vou comparando linha por linha para verificar se alguma linha contém o padrão que utilizo na última linha, caso não encontre, seto uma flag marcando o arquivo como incompleto e em seguida apago ele, da próxima tentativa vou baixar ele novamente, se tiver completo, gravo e finalizo. Ainda que na próxima vez eu busque esse arquivo, ele já vai existir em meu diretório e não vou baixá-lo novamente.

Abaixo, o método get que obtém o arquivo:

public boolean getArquivoFTP(FtpClient client, String filename)
			throws Exception {
		boolean arquivoCompleto = false;

		File dir = new File(diretorio);
		dir.mkdir();

		try {
			File fl = new File(dir, filename);

			if (!fl.exists()) {
				logger.log(Level.INFO, "Transferindo arquivo " + filename);
				InputStream is = client.get(filename);
				BufferedReader br = new BufferedReader(
						new InputStreamReader(is));

				Writer wr = new FileWriter(fl);
				BufferedWriter bw = new BufferedWriter(wr);

				String l;
				String linha;
				while ((l = br.readLine()) != null) {
					linha = (String) l;
					arquivoCompleto = linha.startsWith("ZZ");
					bw.write(linha);
					bw.newLine();
					if (arquivoCompleto) {
						break;
					}
				}
				is.close();
				br.close();
				wr.flush();
				bw.flush();
				wr.close();
				bw.close();

				if (!arquivoCompleto) {
					fl.delete();
				}else {
					logger.log(Level.INFO, "Transferência concluída com sucesso");
				}
				
			}
		} catch (FileNotFoundException fle) {
			logger.log(Level.SEVERE, "Arquivo não encontrado no servidor", fle);
		} catch (IOException ioe) {
			logger.log(Level.SEVERE, "Falha durante processo de leitura/gravação do arquivo", ioe);
		} catch (Exception e) {
			logger.log(Level.SEVERE, "Falha no método getArquivoFTP", e);
			throw e;
		} finally {
			fecharConexaoFTP(client);
		}

		return arquivoCompleto;
	}

Não sei se essa foi a melhor solução possível, a meu ver, se trabalhasse com stream para escrita de dados, assim como trabalhei na leitura, seria mais performático, mas não consegui resolver isso.

Se alguém tiver uma solução mais interessante, será bem vinda.

desculpe ressuscitar o tópico, mas tenho uma duvida, e se o arquivo nao tiver uma ultima linha padrão. Se sempre for um arquivo surpresa e a rede dar uma travada? Como analisar?