IOTools.java
package eu.javaexperience.io;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.CRC32;
import java.util.zip.GZIPInputStream;
import eu.javaexperience.file.AbstractFile;
import eu.javaexperience.file.FileSystemTools;
import eu.javaexperience.interfaces.simple.SimpleCall;
import eu.javaexperience.interfaces.simple.publish.SimplePublish1;
import eu.javaexperience.reflect.Mirror;
import eu.javaexperience.semantic.references.MayNotModified;
import eu.javaexperience.text.StringTools;
public class IOTools
{
static final @MayNotModified byte[] unixLineFeed = new byte[]{'\n'};
static final @MayNotModified byte[] windowsLineFeed = new byte[]{'\r'};
static final @MayNotModified byte[] macLineFeed = new byte[]{'\r','\n'};
public static byte[] loadFileContent(String file) throws IOException
{
try(FileInputStream fis = new FileInputStream(file);)
{
byte[] ret = loadAllAvailableFromInputStream(fis);
return ret;
}
}
public static byte[] loadFileContent(AbstractFile file) throws IOException
{
try(InputStream fis = file.openRead())
{
return loadAllFromInputStream(fis);
}
}
public static final OutputStream nullOutputStream = new OutputStream()
{
@Override public void write(int arg0) throws IOException{}
@Override public void write(byte[] b) throws IOException{}
@Override public void write(byte[] b,int i,int a) throws IOException{}
};
public static Writer nullWriter = new Writer()
{
@Override public void write(char[] paramArrayOfChar, int paramInt1, int paramInt2)throws IOException{}
@Override public void flush() throws IOException{}
@Override public void close() throws IOException{}
};
public static PrintWriter nullPrintWriter = new PrintWriter(nullOutputStream);
public static final InputStream nullInputStream = new InputStream()
{
@Override public int read() throws IOException{return -1;}
};
public static byte[] loadFileProcContent(String file) throws IOException
{
try(FileInputStream fis = new FileInputStream(file);)
{
byte[] ret = loadAllFromInputStream(fis);
return ret;
}
}
public static byte[] getBytesOfFile(String file, int start, int end) throws FileNotFoundException, IOException
{
if(end<= start)
return new byte[0];
try(FileInputStream fis = new FileInputStream(file))
{
if(end > fis.available())
end = fis.available();
if(end <= start)
return new byte[0];
byte[] ret = new byte[end-start];
fis.skip(start);
int ep = 0;
int read = 0;
while((read = fis.read(ret, ep, ret.length-ep))>0)
ep+= read;
return ret;
}
}
public static byte[] loadFromStream(InputStream is,int len) throws FileNotFoundException, IOException
{
if(len <= 0)
return new byte[0];
byte[] ret = new byte[len];
int ep = 0;
int read = 0;
while((read = is.read(ret, ep, ret.length-ep))>0)
ep+= read;
return ret;
}
public static void putFileContent(String file, byte[] data) throws IOException
{
try(FileOutputStream fos = new FileOutputStream(file))
{
fos.write(data);
fos.flush();
}
}
public static void putFileContent(String file, boolean append, byte[] data) throws IOException
{
try(FileOutputStream fos = new FileOutputStream(file, append))
{
fos.write(data);
fos.flush();
}
}
public static void putFileContents(String file, boolean append, byte[]... datas) throws FileNotFoundException, IOException
{
File f = new File(file);
if(!f.exists())
f.createNewFile();
try(FileOutputStream fos = new FileOutputStream(file,append))
{
for(byte[] data:datas)
fos.write(data);
fos.flush();
}
}
/**
* Beolvas mindent a bejövő adatfolyamról az {@link InputStream#available()} metódus segítségével.
* Hatékonyabb mint a {@link #loadAllFromInputStream(InputStream)},
* lehet hogy 1 olvasással végez, viszton az {@link InputStream#available()} nem mindig elérhtő.
* Nem zárja be az adatfolyamot!
* */
public static byte[] loadAllAvailableFromInputStream(InputStream is) throws IOException
{
int ep = 0;
byte[] ret = new byte[is.available()];
while(is.available() > 0)
{
if(ep == ret.length)
ret = Arrays.copyOf(ret, ret.length*2);
ep += is.read(ret, 0, ret.length-ep);
}
return Arrays.copyOf(ret, ep);
}
/**
* Beolvas mindent a bejövő adatfolyamról, az available használata nélkül.
* Lassabb de múködése biztosabb, van hogy az {@link InputStream#available()} kivételt dob.
* Nem zárja be az adatfolyamot!
* */
public static byte[] loadAllFromInputStream(InputStream is) throws IOException
{
int ep = 0;
int read = 0;
byte[] ret = new byte[4096];
while((read = is.read(ret, ep, ret.length-ep))>0)
{
if(ep + read == ret.length)
ret = Arrays.copyOf(ret, ret.length*2);
ep+= read;
}
return Arrays.copyOf(ret, ep);
}
public static byte[] loadAllFromInputStream(InputStream is, int startBuffer) throws IOException
{
int ep = 0;
int read = 0;
byte[] ret = new byte[startBuffer];
while((read = is.read(ret, ep, ret.length-ep))>0)
{
if(ep + read == ret.length)
ret = Arrays.copyOf(ret, ret.length*2);
ep+= read;
}
return Arrays.copyOf(ret, ep);
}
public static int copyStream(InputStream is,OutputStream os) throws IOException
{
int w = 0;
byte[] buff = new byte[4096];
int cr = 0;
while((cr = is.read(buff))> -1)
{
os.write(buff, 0, cr);
w += cr;
}
return w;
}
public static int copyStream(InputStream is,OutputStream os, byte[] buff) throws IOException
{
int w = 0;
int cr = 0;
while((cr = is.read(buff))> -1)
{
os.write(buff, 0, cr);
w += cr;
}
return w;
}
/**
* returns the count of copied bytes, returns -1* copied byte if limit reached
* */
public static int copyStream(InputStream is,OutputStream os, byte[] buff, int limit) throws IOException
{
int w = 0;
int cr = 0;
while((cr = is.read(buff))> -1)
{
os.write(buff, 0, cr);
w += cr;
if(w >= limit)
return -w;
}
return w;
}
public static void silentClose(OutputStream outputStream)
{
try
{
outputStream.close();
}
catch(Exception e)
{}
}
public static void silentClose(InputStream is)
{
try
{
is.close();
}
catch(Exception e)
{}
}
public static void silentClose(Closeable is)
{
try
{
is.close();
}
catch(Throwable e)
{}
}
public static void silentClose(AutoCloseable is)
{
try
{
is.close();
}
catch(Throwable e)
{}
}
public static int writeInputStreamToFile(InputStream is,String file) throws IOException
{
try(FileOutputStream fos = new FileOutputStream(file))
{
int n = copyStream(is, fos);
fos.flush();
return n;
}
}
public static int writeStringToFile(String str,String file) throws IOException
{
byte[] d = str.getBytes();
try(FileOutputStream fos = new FileOutputStream(file))
{
fos.write(d);
fos.flush();
}
return d.length;
}
public static byte[] getFilePart(String file,long off,int len) throws IOException
{
byte[] ret = null;
try(FileInputStream fis = new FileInputStream(file))
{
long skip = fis.skip(off);
while(skip != off)
{
long buf = fis.skip(skip-off);
if(buf < 1)
{
fis.close();
return new byte[0];
}
skip += buf;
}
int s = 0;
ret = new byte[len];
while(s != len)
{
int read = fis.read(ret, s, len-s);
if(read == -1)
{
ret = Arrays.copyOf(ret, s);
break;
}
s+=read;
}
}catch(IOException e)
{
throw e;
}
return ret;
}
public static byte[] md5(String content)
{
try
{
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(content.getBytes());
return md.digest();
}
catch (NoSuchAlgorithmException e)
{
Mirror.propagateAnyway(e);
return null;
}
}
protected static byte[] digestWith(MessageDigest md, String file) throws IOException
{
try(InputStream fis = new FileInputStream(file))
{
byte[] data = new byte[4096];
int read = 0;
while(-1 < (read = fis.read(data)))
{
if(0 == read)
{
continue;
}
else if(data.length == read)
{
md.update(data);
}
else
{
md.update(Arrays.copyOf(data, read));
}
}
}
return md.digest();
}
public static byte[] fileChksumMd5(String file) throws NoSuchAlgorithmException, IOException
{
MessageDigest md = MessageDigest.getInstance("MD5");
return digestWith(md, file);
}
public static byte[] fileChksumCrc32(String file) throws NoSuchAlgorithmException, IOException
{
CRC32 crc32 = new CRC32();
try(InputStream fis = new FileInputStream(file))
{
byte[] data = new byte[4096];
int read = 0;
while(-1 < (read = fis.read(data)))
{
if(0 == read)
{
continue;
}
else if(data.length == read)
{
crc32.update(data);
}
else
{
crc32.update(Arrays.copyOf(data, read));
}
}
}
long val = crc32.getValue();
return new byte[]
{
(byte)((val >> 24)&0xff),
(byte)((val >> 16)&0xff),
(byte)((val >> 8)&0xff),
(byte)((val)&0xff),
};
}
public static byte[] fileChksumSha256(String file) throws NoSuchAlgorithmException, IOException
{
MessageDigest md = MessageDigest.getInstance("SHA-256");
return digestWith(md, file);
}
public static void loadFillAllLine(String file, Collection<String> lines) throws FileNotFoundException, IOException
{
loadFillAllLine(FileSystemTools.DEFAULT_FILESYSTEM.fromUri(file), lines);
}
public static void loadFillAllLine(AbstractFile file, Collection<String> lines) throws FileNotFoundException, IOException
{
try
(
InputStream fis = file.openRead();
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
)
{
String line = null;
while((line = br.readLine()) != null)
{
lines.add(line);
}
}
}
public static String[] readAllLine(File in) throws FileNotFoundException, IOException
{
try
(
FileInputStream fis = new FileInputStream(in);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
)
{
ArrayList<String> re = new ArrayList<>();
String line = null;
while((line = br.readLine()) != null)
{
re.add(line);
}
return re.toArray(Mirror.emptyStringArray);
}
}
public static int linesInFile(File f)
{
try
(
FileInputStream fis = new FileInputStream(f);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
)
{
int count = 0;
while(br.readLine() != null)
{
++count;
}
return count;
}
catch(Exception e)
{
return -1;
}
}
public static void silentFlush(Flushable f)
{
try
{
f.flush();
}
catch(Throwable t)
{}
}
/**
* won't close inputStream
* @throws IOException
* */
public static void processStreamLines(InputStream is, SimplePublish1<String> onReadLine) throws IOException
{
try
(
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
)
{
String line = null;
while((line = br.readLine()) != null)
{
onReadLine.publish(line);
}
}
}
public static void processFileLines(String file, SimplePublish1<String> onReadLine) throws FileNotFoundException, IOException
{
try(FileInputStream fis = new FileInputStream(file))
{
processStreamLines(fis, onReadLine);
}
}
public static String getFileContents(String string) throws FileNotFoundException, IOException
{
try(FileInputStream fis = new FileInputStream(string))
{
return new String(loadAllFromInputStream(fis));
}
}
public static String getFileContents(File string) throws FileNotFoundException, IOException
{
try(FileInputStream fis = new FileInputStream(string))
{
return new String(loadAllFromInputStream(fis));
}
}
public static String getFileContents(AbstractFile file) throws FileNotFoundException, IOException
{
try(InputStream fis = file.openRead())
{
return new String(loadAllFromInputStream(fis));
}
}
public static byte[] getURL(URL url) throws IOException
{
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
try
{
return IOTools.loadAllFromInputStream(conn.getInputStream());
}
finally
{
IOTools.silentClose(is);
}
}
public static void feedAllLine(String file, SimplePublish1<String> feed) throws IOException
{
try
(
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
)
{
String line = null;
while(null != (line = br.readLine()))
{
feed.publish(line);
}
}
}
public static SimpleCall readAllStdInLine(final SimplePublish1<String> feed)
{
return new SimpleCall()
{
@Override
public void call()
{
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while(null != (line = br.readLine()))
{
feed.publish(line);
}
}
catch(Exception e)
{
Mirror.propagateAnyway(e);
}
}
};
}
public static String[] readAllLine(String string) throws FileNotFoundException, IOException
{
return readAllLine(new File(string));
}
public static void createPathBeforeFile(File file)
{
createPathBeforeFile(file.toString());
}
public static void createPathBeforeFile(String file)
{
if(file.endsWith("/"))
{
new File(file).mkdirs();
}
else
{
String path = StringTools.getSubstringBeforeLastString(file, "/", null);
if(null != path)
{
new File(path).mkdirs();
}
}
}
public static String readLine_rn(InputStream is, byte[] buffer, int max) throws IOException
{
if(is.markSupported())
{
return readLine_rn_withMarkSupport(is, buffer, max);
}
int ep = 0;
for(int i=0;i<max;++i)
{
int read = is.read();
if(0 > read)
{
//no more line
if(0 == i)
{
return null;
}
else
{
//returns with the line
break;
}
}
if('\r' == read)
{
//ignore
continue;
}
//line feed after CR, line is ended
else if('\n' == read)
{
//returns with the Line
break;
}
else
{
buffer[ep++] = (byte) read;
}
}
return new String(buffer, 0, ep);
}
protected static String readLine_rn_withMarkSupport(InputStream is, byte[] buffer, int max) throws IOException
{
is.mark(max);
int size = is.read(buffer);
int index = -1;
for(int i=0;i<size;++i)
{
if('\n' == buffer[i])
{
index = i;
break;
}
}
if(-1 == index)
{
is.reset();
return null;
}
if(0 == index)
{
return "";
}
is.reset();
is.skip(index+1);
return new String(buffer, 0, index-1);
}
public static void appendData(String file, byte[] data) throws IOException
{
try(OutputStream os = new FileOutputStream(file, true))
{
os.write(data);
os.flush();
}
}
public static void copyFileContentToStream(File f, OutputStream os) throws FileNotFoundException, IOException
{
try(InputStream is = new FileInputStream(f))
{
IOTools.copyStream(is, os);
}
}
/**
* Origin from: java.lang.String
*@param source the characters being searched.
* @param sourceOffset offset of the source string.
* @param sourceCount count of the source string.
* @param target the characters being searched for.
* @param targetOffset offset of the target string.
* @param targetCount count of the target string.
* @param fromIndex the index to begin searching from.
*/
public static int indexOfBytes(byte[] source, int sourceOffset, int sourceCount, byte[] target, int targetOffset, int targetCount, int fromIndex)
{
if (fromIndex >= sourceCount)
{
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
byte first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first);
}
/* Found first character, now look at the rest of v2 */
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && source[j]
== target[k]; j++, k++);
if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}
public static int indexOfBytes(byte[] source, byte[] target, int fromIndex, int endindex)
{
return indexOfBytes(source, 0, endindex, target, 0, target.length, fromIndex);
}
public static int readFull(InputStream is, byte[] data) throws IOException
{
int off = 0;
int read = 0;
while(off < data.length && (read = is.read(data, off, data.length-off)) > -1)
{
off += read;
}
return off;
}
public static String tryGetContent(AbstractFile file, String _default)
{
try
{
return getFileContents(file);
}
catch(Exception e)
{
return _default;
}
}
public static void ungzip(File from, File to) throws FileNotFoundException, IOException
{
try
(
InputStream is = new FileInputStream(from);
GZIPInputStream gin = new GZIPInputStream(is);
OutputStream os = new FileOutputStream(to);
)
{
IOTools.copyStream(gin, os);
os.flush();
}
}
protected static final class IoToolsShutdownAutoClose
{
protected static Set<Closeable> CLOSE_ON_EXIT = new HashSet<>();
static
{
Runtime.getRuntime().addShutdownHook
(
new Thread()
{
@Override
public void run()
{
Closeable[] close;
synchronized(CLOSE_ON_EXIT)
{
close = CLOSE_ON_EXIT.toArray(new Closeable[0]);
}
for(Closeable c:close)
{
silentClose(c);
}
}
}
);
}
}
public static void closeOnExit(Closeable close)
{
if(null == close)
{
return;
}
synchronized(IoToolsShutdownAutoClose.CLOSE_ON_EXIT)
{
IoToolsShutdownAutoClose.CLOSE_ON_EXIT.add(close);
}
}
public static void revokeCloseOnExit(Closeable close)
{
if(null == close)
{
return;
}
synchronized(IoToolsShutdownAutoClose.CLOSE_ON_EXIT)
{
IoToolsShutdownAutoClose.CLOSE_ON_EXIT.remove(close);
}
}
public static boolean isCloseOnExit(Closeable close)
{
if(null == close)
{
return false;
}
synchronized(IoToolsShutdownAutoClose.CLOSE_ON_EXIT)
{
return IoToolsShutdownAutoClose.CLOSE_ON_EXIT.contains(close);
}
}
}