File download problem in my scala code - scala

I have written the following scala code to download a file . The file gets downloaded correctly but also an exception is thrown. The code is as follows :
var out:OutputStream = null
var in:InputStream = null
try {
var url:URL = null
url = new URL("http://somehost.com/file.doc")
val uc = url.openConnection()
val connection = uc.asInstanceOf[HttpURLConnection]
connection.setRequestMethod("GET")
val buffer:Array[Byte] = new Array[Byte](1024)
var numRead:Int = 0
in = connection.getInputStream()
var localFileName="test.doc"
out = new BufferedOutputStream(new FileOutputStream(localFileName))
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer,0,numRead);
}
}
catch {
case e:Exception => println(e.printStackTrace())
}
out.close()
in.close()
The file gets downloaded but the following exception is thrown :
java.lang.IndexOutOfBoundsException
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:260)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
at TestDownload$.main(TestDownload.scala:34)
at TestDownload.main(TestDownload.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
()
Why could this be happening and any way to fix it ?
Please Help
Thank You

Scala returns type Unit, not the type of the value being assigned, with an assignment statement. So
numRead = in.read(buffer)
never returns -1; it doesn't even return an integer. You can write
while( { numRead = in.read(buffer); numRead != -1 } ) out.write(buffer, 0, numRead)
or you can go for a more functional style with
Iterator.continually(in.read(buffer)).takeWhile(_ != -1).foreach(n => out.write(buffer,0,n))
Personally, I prefer the former since it's shorter (and relies less on iterator evaluation happening the way "it ought to").

An alternative option is to use the system commands which is much cleaner and faster from what I can tell.
import sys.process._
import java.net.URL
import java.io.File
new URL("http://somehost.com/file.doc") #> new File("test.doc") !!

Related

IndexOutBoundException While Copying Image File [duplicate]

I have written the following scala code to download a file . The file gets downloaded correctly but also an exception is thrown. The code is as follows :
var out:OutputStream = null
var in:InputStream = null
try {
var url:URL = null
url = new URL("http://somehost.com/file.doc")
val uc = url.openConnection()
val connection = uc.asInstanceOf[HttpURLConnection]
connection.setRequestMethod("GET")
val buffer:Array[Byte] = new Array[Byte](1024)
var numRead:Int = 0
in = connection.getInputStream()
var localFileName="test.doc"
out = new BufferedOutputStream(new FileOutputStream(localFileName))
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer,0,numRead);
}
}
catch {
case e:Exception => println(e.printStackTrace())
}
out.close()
in.close()
The file gets downloaded but the following exception is thrown :
java.lang.IndexOutOfBoundsException
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:260)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
at TestDownload$.main(TestDownload.scala:34)
at TestDownload.main(TestDownload.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
()
Why could this be happening and any way to fix it ?
Please Help
Thank You
Scala returns type Unit, not the type of the value being assigned, with an assignment statement. So
numRead = in.read(buffer)
never returns -1; it doesn't even return an integer. You can write
while( { numRead = in.read(buffer); numRead != -1 } ) out.write(buffer, 0, numRead)
or you can go for a more functional style with
Iterator.continually(in.read(buffer)).takeWhile(_ != -1).foreach(n => out.write(buffer,0,n))
Personally, I prefer the former since it's shorter (and relies less on iterator evaluation happening the way "it ought to").
An alternative option is to use the system commands which is much cleaner and faster from what I can tell.
import sys.process._
import java.net.URL
import java.io.File
new URL("http://somehost.com/file.doc") #> new File("test.doc") !!

ZipInputStream.read in ZipEntry

I am reading zip file using ZipInputStream. Zip file has 4 csv files. Some files are written completely, some are written partially. Please help me find the issue with below code. Is there any limit on reading buffer from ZipInputStream.read method?
val zis = new ZipInputStream(inputStream)
Stream.continually(zis.getNextEntry).takeWhile(_ != null).foreach { file =>
if (!file.isDirectory && file.getName.endsWith(".csv")) {
val buffer = new Array[Byte](file.getSize.toInt)
zis.read(buffer)
val fo = new FileOutputStream("c:\\temp\\input\\" + file.getName)
fo.write(buffer)
}
You have not closed/flushed the files you attempted to write. It should be something like this (assuming Scala syntax, or is this Kotlin/Ceylon?):
val fo = new FileOutputStream("c:\\temp\\input\\" + file.getName)
try {
fo.write(buffer)
} finally {
fo.close
}
Also you should check the read count and read more if necessary, something like this:
var readBytes = 0
while (readBytes < buffer.length) {
val r = zis.read(buffer, readBytes, buffer.length - readBytes)
r match {
case -1 => throw new IllegalStateException("Read terminated before reading everything")
case _ => readBytes += r
}
}
PS: In your example it seems to be less than required closing }s.

null check in while loop in Scala, unusual behaviour

I am aggregating the contents of an InputStream using a BufferedReader using the form
while( (str = br.readLine()) != null){
sb.append(str)
}
but this quickly caused an OutOfMemoryError as the null check failed to pick up the null and my StringBuffer keeps increasing in size...
I have verified that str does have a value of null and also verified that it is not "null".
Refactoring my code to
str = br.readLine()
while(str != null){
sb.append(str)
str = br.readLine()
}
works but I've no idea how this would be any different. Any ideas?
In scala the expression str = br.readline() yield return value of type Unit, which is always not equal to null. It should have given you a warning about comparing Unit to null.
You are correct to refactor it like that.
P.S. As #Jesper correctly commented your question, this is not the way you usually read a file in scala. So if you do that - please use his code example. If you have any other InputStream, you can use Source.fromInputStream
Archeg has explained it beautifully so try this :
var str = ""
while({str = br.readLine; str != null}) {
}
and since you are working in Scala, try using
scala.io.Source.fromInputStream(is).getLines().mkString("\n")
or
val bufferedReader = new BufferedReader(inputStreamReader)
Iterator continually bufferedReader.readLine takeWhile (_ != null) mkString

Specify Variable Initialization Order in Scala

I have a special class Model that needs to have its methods called in a very specific order.
I tried doing something like this:
val model = new Model
new MyWrappingClass {
val first = model.firstMethod()
val second = model.secondMethod()
val third = model.thirdMethod()
}
The methods should be called in the order listed, however I am seeing an apparently random order.
Is there any way to get the variable initialization methods to be called in a particular order?
I doubt your methods are called in the wrong order. But to be sure, you can try something like this:
val (first, second, third) = (
model.firstMethod(),
model.secondMethod(),
model.thirdMethod()
)
You likely have some other problem with your code.
I can run 100 million loops where it never gets the order wrong, as follows:
class Model {
var done = Array(false,false,false);
def firstMethod():Boolean = { done(0) = true; done(1) || done(2) };
def secondMethod():Boolean = { done(1) = true; !done(0) || done(2) };
def thirdMethod():Boolean = { done(2) = true; !done(0) || !done(1) };
};
Notice that these methods return a True if done out of order and false when called in order.
Here's your class:
class MyWrappingClass {
val model = new Model;
val first = model.firstMethod()
val second = model.secondMethod()
val third = model.thirdMethod()
};
Our function to check for bad behavior on each trial:
def isNaughty(w: MyWrappingClass):Boolean = { w.first || w.second || w.third };
A short program to test:
var i = 0
var b = false;
while( (i<100000000) && !b ){
b = isNaughty(new MyWrappingClass);
i += 1;
}
if (b){
println("out-of-order behavior occurred");
println(i);
} else {
println("looks good");
}
Scala 2.11.7 on OpenJDK8 / Ubuntu 15.04
Of course this doesn't prove it impossible to have wrong order, only that correct behavior seems highly repeatable in a fairly simple case.

noSuchElement exception with nextInt() method

Hey guys I don't get why I get an exception in this simple code
I'm trying to make a card game, and try to read the users wanted index of the card in his hand (it's in German)
public Karte abschlagen(Karte gegnK) {
System.out
.println("Bitte die Zahl für die jeweilige Karte auswählen: ");
gibHandAus(); // prints the users cards with their indexes
try {
Scanner sc = new Scanner(System.in);
int index = sc.nextInt();
if (index < 0 || index >= getHand().size()) {
System.out
.println("Bitte nur eine der gegebenen Zahlen auswählen!");
sc.close();
return abschlagen(gegnK);
}
Karte k = getHand().get(index);
getHand().remove(index);
sc.close();
So what's the problem here?
Before I can choose a number, it throws the noSuchElement exception.
I read in another question that the close() method can be causing this, but it still did it without it.
The error message is:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at durak.Spiel.spielerWehrtAb(Spiel.java:229)
at durak.Spiel.main(Spiel.java:314)
EDIT: Code of spielerWehrAb():
public static boolean spielerWehrtAb(Karte k) {
.
.
.
try {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
sc.close();
if (x == 0) {
... }
else if(x == 1) {
System.out.println("1 ausgewählt");
Karte k2 = spieler.abschlagen(k);
....
}
else return spielerWehrAb(k);
The problem is Scanner.close(); closes the underlying stream. The second time, you're trying to read from a closed stream, so it obviously fails.
Please see the tests I designed to demonstrate this behavior here: java.util.Scanner strange behaviour when used with System.in
The solution would be not to read after closing the Scanner. You could, for example, define the Scanner as a class member and always use that member.