I'm trying to optimise the code below , would it be possible to directly ScreenCap to Byte Array so I can skip the step of saving it into memory.
Process sh = Runtime.getRuntime().exec("su", null,null);
OutputStream os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + "/sdcard/colorPickerTemp.png").getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();
InputStream inputStream = new FileInputStream("/sdcard/colorPickerTemp.png");//You can get an inputStream using any IO API
byte[] bytes;
byte[] buffer = new byte[1000000];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
while ((bytesRead = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
bytes = output.toByteArray();
final String encodedString = Base64.encodeToString(bytes, Base64.DEFAULT);
Screencap usage:
"usage: %s [-hp] [-d display-id] [FILENAME]\n"
" -h: this message\n"
" -p: save the file as a png.\n"
" -d: specify the display id to capture, default %d.\n"
"If FILENAME ends with .png it will be saved as a png.\n"
"If FILENAME is not given, the results will be printed to stdout.\n"
So you can do something like this:
public String getScreenshotBase64() throws IOException {
return Base64.encodeToString(getScreenshotImageBytes(), Base64.NO_WRAP);
}
public byte[] getScreenshotImageBytes() throws IOException {
Process process = Runtime.getRuntime().exec("su");
OutputStreamWriter outputStream = new OutputStreamWriter(process.getOutputStream());
outputStream.write("/system/bin/screencap -p\n");
outputStream.flush();
byte[] bytes = readBytes(process.getInputStream());
outputStream.write("exit\n");
outputStream.flush();
outputStream.close();
return bytes;
}
public byte[] readBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
Related
So im making a client-server based architecture programm where server is sending a file and client receives it.
I have seen a lot of code parts and i also made a lot where i send small files. ex images. In my case i want to send .wav audio files which are large(40mb). This is what i have done so far. When i run my client, it just proceed to download, but never really downloads the file. I guess its because its too large.
How to send such large files?
server
public void send_file_to_client(String requested_file) throws IOException {
FileInputStream fis = null;
BufferedInputStream bis = null;
File FILE_TO_SEND = new File("C:\\ServerMusicStorage\\" + requested_file + ".wav");
byte[] mybytearray = new byte[(int) FILE_TO_SEND.length()];
try {
fis = new FileInputStream(FILE_TO_SEND);
bis = new BufferedInputStream(fis);
} catch (FileNotFoundException ex) {
Logger.getLogger(ClientHandler.class.getName()).log(Level.SEVERE, null, ex);
}
OutputStream os = null;
bis.read(mybytearray, 0, mybytearray.length);
os = connsock.getOutputStream();
System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)");
toClient.writeUTF(Integer.toString(mybytearray.length));
os.write(mybytearray, 0, mybytearray.length);
os.flush();
System.out.println("Done.");
if (bis != null) {
bis.close();
}
if (os != null) {
os.close();
}
if (connsock != null) {
connsock.close();
}
}
client
public static void receive_file(String requested_file) throws IOException {
File file_to_save = new File("C:\\ClientMusicStorage\\" + requested_file + ".wav");
int bytesRead;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
//get file size to create the bytearray
String fileSize=fromServer.readUTF();
int final_file_size = Integer.parseInt(fileSize);
byte[] mybytearray = new byte[final_file_size];
InputStream is = clientSocket.getInputStream();
fos = new FileOutputStream(file_to_save);
bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray, 0, mybytearray.length);
current = bytesRead;
do {
bytesRead
= is.read(mybytearray, current, (mybytearray.length - current));
if (bytesRead >= 0) {
current += bytesRead;
}
} while (bytesRead > -1);
bos.write(mybytearray, 0, current);
bos.flush();
}
I am writing a raw socket server (for learning purpose), which on any request, should parse the Content-Length header and should then extract bytes equal to Content-Length from the socket input stream and echo it back to the client.
I found only one class 'DataInputStream' in Java IO system that provides with the capabilities of reading both, characters and bytes. However, the method readLine() of 'DataInputStream' is deprecated which I am using in my code. How can I get rid of the deprecated readLine() method in following code? Is there any class in Java IO system that allows reading of both, characters and bytes. Code follows:
class Server {
public Server() {
}
public void run() throws IOException {
ServerSocket serverSocket = new ServerSocket(7000);
while (true) {
Socket socket = serverSocket.accept();
DataInputStream requestStream = new DataInputStream(
new BufferedInputStream(socket.getInputStream()));
byte[] responseContent = null;
int contentLength = getContentLength(requestStream);
if (contentLength == 0)
responseContent = new byte[0];
else {
int totalBytesRead = 0, bytesRead = 0;
final int bufferSize = 5120;
final byte[] buffer = new byte[bufferSize];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
while (totalBytesRead != contentLength) {
bytesRead = requestStream.read(buffer, 0, bufferSize);
outputStream.write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
}
responseContent = outputStream.toByteArray();
}
OutputStream outputStream = socket.getOutputStream();
PrintWriter writer = new PrintWriter(outputStream);
writer.println(String.format("HTTP/1.1 %s", 200));
writer.println(String.format("Content-Length: %d", contentLength));
writer.println("");
writer.flush();
outputStream.write(responseContent);
outputStream.flush();
socket.close();
}
}
private int getContentLength(DataInputStream requestStream)
throws IOException {
int contentLength = 0;
String headerLine;
// TODO - Get rid of deprecated readLine() method
while ((headerLine = requestStream.readLine()) != null
&& headerLine.length() != 0) {
final String[] headerTokens = headerLine.split(":");
if (headerTokens[0].equalsIgnoreCase("Content-Length")) {
contentLength = Integer.valueOf(headerTokens[1].trim());
}
}
return contentLength;
}
}
I'm trying to send my image from android client to Java server. Size of image that i'm sending is about 99kb, but server always reads a few kb less, sometimes 98, sometimes 96 and so on. I'd like to know why that data is lost and how can I send image in a proper way. Please help :)
Code:
Client(sending image):
public void sendImage(File file){
try {
out = new PrintWriter(socket.getOutputStream(),true);
out.println("Image");
out.println(file.length());
byte[] byteArray = new byte[(int) file.length()];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(byteArray,0,byteArray.length);
OutputStream os = socket.getOutputStream();
FilterOutputStream bos = new FilterOutputStream(os);
bos.write(byteArray,0,byteArray.length);
bos.flush();
os.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Server(receiving image):
if(input.equals("Image")){
input = in.readLine();
int fileSize = Integer.parseInt(input);
System.out.println("FILESIZE:" +fileSize);
byte[] byteArray = new byte[fileSize];
FileOutputStream fileOutputStream =
new FileOutputStream("filename.jpg");
BufferedOutputStream bos =
new BufferedOutputStream(fileOutputStream);
BufferedInputStream bis = new BufferedInputStream(in_);
int bytesRead = bis.read(byteArray, 0, byteArray.length);
int current = bytesRead;
do {
bytesRead = bis.read(byteArray, current,
(byteArray.length - current));
if (bytesRead >= 0) {
current += bytesRead;
System.out.println(current);
}
} while (bytesRead != -1);
bos.write(byteArray, 0, current);
bos.flush();
bos.close();
}
EDIT
Problem solved, working code is as follows:
Client side:
public void sendImage(File file){
try {
DataOutputStream out = new DataOutputStream(
socket.getOutputStream());
out.writeChar('I');
DataInputStream dis = new DataInputStream(new FileInputStream(file));
ByteArrayOutputStream ao = new ByteArrayOutputStream();
int read = 0;
byte[] buf = new byte[1024];
while ((read = dis.read(buf)) > -1) {
ao.write(buf, 0, read);
}
out.writeLong(ao.size());
out.write(ao.toByteArray());
out.flush();
out.close();
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Server side:
if(input =='I'){
DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
long length = dis.readLong();
File to = new File("filename.jpg");
DataOutputStream dos = new DataOutputStream(
new FileOutputStream(to));
byte[] buffer = new byte[1024];
int len, current = 0;
System.out.println(length);
while ( current != length) {
len = dis.read(buffer);
dos.write(buffer, 0, len);
current += len;
System.out.println(current);
}
dis.close();
dos.close();
}
From my personal experience PrintWriter and Buffers dont work well together..
As buffers trying to read data before you tell it to it can "steal" data that it should not do. For example if you use any kind of buffered reader to read the input on the server side that buffer will steal some parts at the "start" of the incomming image becuase it think's it's just another line. You could always try using DataInputStream and DataOutputStream instead..
Client:
public void sendImage(File file) {
try {
DataOutputStream out = new DataOutputStream(
socket.getOutputStream());
out.writeChar('I'); // as image,
DataInputStream dis = new DataInputStream(new FileInputStream(file));
ByteArrayOutputStream ao = new ByteArrayOutputStream();
int read = 0;
byte[] buf = new byte[1024];
while ((read = dis.read(buf)) > -1) {
ao.write(buf, 0, read);
}
out.writeLong(ao.size());
out.write(ao.toByteArray());
out.flush();
out.close();
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Server:
// assuming folder structure exists.
public void readImage(Socket s, File to) throws IOException {
DataInputStream dis = new DataInputStream(s.getInputStream());
char c = dis.readChar();
if (c == 'I') {
long length = dis.readLong();
DataOutputStream dos = new DataOutputStream(
new FileOutputStream(to));
byte[] buffer = new byte[1024];
int len;
while ((len = dis.read(buffer)) != -1) {
dos.write(buffer, 0, len);
}
dis.close();
dos.close();
}
}
As a starting point, in the client side, you will also need a loop for reading the local image, because are you sure that...
bis.read(byteArray,0,byteArray.length);
... is really reading the whole image? So you will also need a loop as in the server side.
I want to return file (read or load) from method and then remove this file.
public File method() {
File f = loadFile();
f.delete();
return f;
}
But when I delete a file, I delete it from disk and then exists only descriptor to non-existing file on return statement. So what is the most effective way for it.
You can't keep the File handle of deleted file, rather you can keep the data in a byte array temporarily, delete the file and then return the byte array
public byte[] method() {
File f =loadFile();
FileInputStream fis = new FileInputStream(f);
byte[] data = new byte[fis.available()];
fis.read(data);
f.delete();
return data;
}
// Edit Aproach 2
FileInputStream input = new FileInputStream(f);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int bytesRead = input.read(buf);
while (bytesRead != -1) {
baos.write(buf, 0, bytesRead);
bytesRead = input.read(buf);
}
baos.flush();
byte[] bytes = baos.toByteArray();
you can construct the file data from byte array
However, my suggestion is to use IOUtils.toByteArray(InputStream input) from Jakarta commons, why do you want re write when already in plate
Assuming you want to return the file to the browser, this is how I did it :
File pdf = new File("file.pdf");
if (pdf.exists()) {
try {
InputStream inputStream = new FileInputStream(pdf);
httpServletResponse.setContentType("application/pdf");
httpServletResponse.addHeader("content-disposition", "inline;filename=file.pdf");
copy(inputStream, httpServletResponse.getOutputStream());
inputStream.close();
pdf.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
private static int copy(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[512];
int count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
I am trying to build a file transfer mechanism between 2 Java socket client. The sender client would include this sorta snippet:
FileInputStream fis = null;
BufferedInputStream bis = null;
BufferedOutputStream outStream = null;
byte[] fileBytes = new byte[(int) file.length()];
int bytesRead = 0;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
outStream = new BufferedOutputStream(socket.getOutputStream());
bytesRead = bis.read(fileBytes, 0, fileBytes.length);
outStream.write(fileBytes, 0, fileBytes.length);
} catch (IOException _IOExc) {
Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE,
null, _IOExc);
//QuitConnection(QUIT_TYPE_DEFAULT);
}
The server mediator would look like:
public void run() {
assert (outSocket != null);
byte[] bytes = new byte[fileSize];
try {
System.out.println("inStream " + inStream.available());
outStream = new BufferedOutputStream(outSocket.getOutputStream());
inStream.read(bytes, 0, fileSize);
outStream.write(bytes, 0, fileSize);
outStream.flush();
} catch (IOException ex) {
Logger.getLogger(FileTransport.class.getName()).log(Level.SEVERE,
null, ex);
}
}
the destination client:
public void run() {
try {
System.out.println("Start reading...");
int len = 1024;
BufferedInputStream inStream = new BufferedInputStream
(client.user.getClientSocket().getInputStream());
while ((bytesRead = inStream.read(fileBytes, 0, len)) >
0 && current < fileSize) {
current = current + bytesRead;
System.out.println("current "+ current);
bos.write(fileBytes, 0, bytesRead < len ? bytesRead : len);
}
bos.flush();
bos.close();
} catch (IOException ex) {
Logger.getLogger(ReadFileThread.class.getName()).log(Level.SEVERE,
null, ex);
} catch (InterruptedException e) {
}
}
Both the server and destination client is passed "fileSize" in advance, the problem now is server side get slight less data and the clientB keep reading only 8192 bytes of data from server and can never get out the loop.
Many thanks
Kev
Don't ignore the result of the read() method. It returns the number of bytes that have been read, which is not necessarily the length of the file. read() must always be called in a loop, until it returns -1.
And don't, ever, use available(). It doesn't return what you think it returns. Just loop until read() returns -1 or until the number of read bytes reaches the expected count.
Read the IO tutorial.