java : What is the exact functionality of buffer.flip() method? - java-io

try (FileOutputStream binFile = new FileOutputStream("data.dat");
FileChannel binChannel = binFile.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(100);
byte[] outputBytes = "Hello World!".getBytes();
buffer.put(outputBytes);
long int1Pos = outputBytes.length;
buffer.putInt(245);
binChannel.write(buffer);
java.io.RandomAccessFile ra = new java.io.RandomAccessFile("data.dat", "rwd");
FileChannel channel = ra.getChannel();
ByteBuffer readBuffer = ByteBuffer.allocate(100);
channel.position(int1Pos);
channel.read(readBuffer);
readBuffer.flip();
System.out.println("Int3 = " + readBuffer.getInt());
} catch(IOException e){
}

You should checkout the Java docs on it. https://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html
Flips this buffer. The limit is set to the current position and then the position is set to zero. If the mark is defined then it is discarded.
After a sequence of channel-read or put operations, invoke this method to prepare for a sequence of channel-write or relative get operations. For example:

Related

getting NegativeByteArraySizeException from ContentResolver's openAssetFileDescriptor method for reading vCardUri. Is there any workaround to fix it?

I am creating a .VCF file for backing up the Contacts. The process of creating and inserting the data get failed because of the FileDescriptor's method getDeclaredLength which returns the size -1 for the length of the vCard-URI which I got from the ContentResolver's openAssetFileDiscritor method.
This is the exact same Question as asked here by Balakrishna Avulapati. but the only problem for asking the same question here is that, the proposed solution is a bit hard for me to understand. which do not salve my problem. The comment by #pskink in the solution of above link could be useful but i am anable to find the full source code, as there is only 1 line provided in the comment.
I am using the fllowing code,
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
AssetFileDescriptor fd = resolver.openAssetFileDescriptor(uri, "r");
FileInputStream fis = fd.createInputStream();
byte[] b = new byte[(int)fd.getDeclaredLength()];
fis.read(b);
Please give your kind sugestions. Thank you :)
So I figured it out by myself, and I'm posting the answer in case of somebody get the similar problem and stuck for the solution. So the code before byte[] b = new byte[(int)fd.getDeclaredLength()]; is same. Change this line to byte[] buf = readBytes(fis); and the method readBytes(FileInputStream fis) is below.
public byte[] readBytes(InputStream inputStream) throws IOException {
// this dynamically extends to take the bytes you read
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
// this is storage overwritten on each iteration with bytes
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
// we need to know how may bytes were read to write them to the byteBuffer
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
// and then we can return your byte array.
return byteBuffer.toByteArray();
}
Hope this help. Cheers

Azure Page Blob OpenRead does not fetch more than StreamMinimumReadSizeInBytes

I have a page blob containing effectively log data. Everything works fine until the log fills up past 2 MB.
When Reading, I'm using the OpenReadAsync method to get a stream from which I read data out of. Prior to calling OpenReadAsync, I set StreamMinimumReadSizeInBytes to 2MB (2 * 1024 * 1024).
After opening the stream, I use the following method to read data out.
public IEnumerable<object> Read(Stream pageAlignedEventStream, long? maxBytes = null)
{
while (pageAlignedEventStream.Position < (maxBytes ?? pageAlignedEventStream.Length))
{
byte[] bytesToReadBuffer = new byte[LongZero.Length];
pageAlignedEventStream.Read(bytesToReadBuffer, 0, LongZero.Length);
long bytesToRead = BitConverter.ToInt64(bytesToReadBuffer, 0);
if (bytesToRead == 0)
{
yield break;
}
if (bytesToRead < 0)
{
throw new InvalidOperationException("Invalid size specification. Stream may be corrupted.");
}
if (bytesToRead > Int32.MaxValue)
{
throw new InvalidOperationException("Payload size is too large.");
}
byte[] payload = new byte[bytesToRead];
int read = pageAlignedEventStream.Read(payload, 0, (int) bytesToRead);
if (read != bytesToRead)
{
// when fails, read == 503, bytesToRead = 3575, position = 2MB (2*1024*14024)
throw new InvalidOperationException("Did not read expected number of bytes.");
}
yield return this.EventSerializer.DeserializeFromStream(new MemoryStream(payload, false));
var paddedSpaceToSkip = PagesRequired(bytesToRead) * PageSizeBytes - bytesToRead - LongZero.Length;
pageAlignedEventStream.Position += paddedSpaceToSkip;
}
yield break;
}
As noted in the comments in the code, the failure happends when the position reaches the 2MB specified. The read fails to pull additional bytes before returning and only reads 503 bytes instead of the expected 3575 bytes.
My expectation was that as I read past the buffer size, it would download more data.
I found a similar issue on Azure Feedback, but linked issue indicates a non-power-of-2 buffersize but 2MB is definitely power of 2.
I could fetch the all data (Size=3MB) that stored in a page blob even though I set StreamMinimumReadSizeInBytes property of CloudPageBlob to 2MB.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("mycontainername");
container.CreateIfNotExists();
CloudPageBlob pageBlob = container.GetPageBlobReference("mypageblob");
pageBlob.StreamMinimumReadSizeInBytes = 2 * 1024 * 1024;
Task<Stream> pageAlignedEventStream = pageBlob.OpenReadAsync();
The read fails to pull additional bytes before returning and only reads 503 bytes instead of the expected 3575 bytes.
If that many bytes are not currently available and the end of the stream has been reached, the returned value could be less than the number of bytes requested. Please debug your code to trace the changes of variable of paddedSpaceToSkip and check whether your code logic is as expected.

Using appium how can we read/print complete list in a drop down in native as well as Hybrid application?

I want to print or read complete contact list using appium (suppose my .apk is a contact application and it shows complete A to Z contacts and by scrolling i can view all of the contacts).
I am able to count/print contacts shown in the first screen (i.e the screen which shows some contact say 10 contacts by default and for more i have to scroll).i have come to solution of the above and its working for some time but after that it throws an error, Please help how to rectify this issue
java.lang.IndexOutOfBoundsException: Index: 9, Size: 9
My code is `
AppiumDriver driver = null;
ArrayList values = new ArrayList();
DesiredCapabilities cap = new DesiredCapabilities();
cap.setCapability(MobileCapabilityType.DEVICE_NAME, "Galaxy S4");
cap.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
cap.setCapability(MobileCapabilityType.PLATFORM_VERSION, "4.4.4");
cap.setCapability(MobileCapabilityType.APP_PACKAGE, "com.brainworks.contacts");
cap.setCapability(MobileCapabilityType.APP_ACTIVITY, "com.brainworks.contacts.ui.Main");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),cap);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
List<WebElement> allContactsOnfirstScreen = driver.findElements(By.xpath("//*[#resource-id='com.brainworks.contacts:id/txt_name']"));
driver.context("NATIVE_APP");
Dimension size = driver.manage().window().getSize();
int StartY = (int)(size.height * 0.70);
int EndY = (int)(size.height * 0.55);
int StartX = size.width/2;
for(int i =0;i<200;i++){
System.out.println("Contacts are = " + allContactsOnfirstScreen.get(i).getAttribute("text"));
String Values = allContactsOnfirstScreen.get(i).getAttribute("text");
values.add(Values);
System.out.println("Value is = " + values);
String ext = Values;
String [] a = ext.split(",");
String [] b = a[a.length-1].split("//]");
System.out.println("val = " + b[0]);
driver.swipe(StartX, StartY, StartX, EndY , 1000);
}`
Second way which i have tried
AppiumDriver driver = null;
// desired cap as above in the first try
// same as above -but now what i am doing is i am printing the list in for loop
// then do a swipe form last element to first element then again print the new list
// and this cycle keeps on running until i reach the end of the list or the parameter
// in the if loop.
int XOfFirstElement = allContactsOnfirstScreen.get(0).getLocation().getX();
int YOfFirstElement = allContactsOnfirstScreen.get(0).getLocation().getY();
System.out.println("X for XOfFirstElement = " + XOfFirstElement);
System.out.println("Y for YOfFirstElement = " + YOfFirstElement);
int XOfLastElement = allContactsOnfirstScreen.get(allContactsOnfirstScreen.size()-1).getLocation().getX();
int YOfLastElement = allContactsOnfirstScreen.get(allContactsOnfirstScreen.size()-1).getLocation().getY();
System.out.println("X for XOfLastElement = " + XOfLastElement);
System.out.println("Y for YOfLastElement = " + YOfLastElement);
int XOfSecondLastElement = allContactsOnfirstScreen.get(allContactsOnfirstScreen.size()-2).getLocation().getX();
int YOfSecondLastElement = allContactsOnfirstScreen.get(allContactsOnfirstScreen.size()-2).getLocation().getY();
System.out.println("X for XOfSecondLastElement = " + XOfSecondLastElement);
System.out.println("Y for YOfSecondLastElement = " + YOfSecondLastElement);
while(true){
for(int i = 0 ;i<allContactsOnfirstScreen.size();i++){
System.out.println("Value is for " + allContactsOnfirstScreen.get(i).getAttribute("text"));
}
driver.swipe(XOfLastElement, YOfLastElement, XOfFirstElement, YOfFirstElement, 1000);
Thread.sleep(1000L);
String LastName = allContactsOnfirstScreen.get(allContactsOnfirstScreen.size()-1).getAttribute("text");
if(LastName.equals("MyLastContactText"))
break;
}
Now the problem is
1.>Every thing is working as expected but what is happening is sometime it prints the duplicate value (Contact) (may be due to coordinates for that contact do not changes after a swipe)
2. i am not able to print the last contact name every time cause my if statement in the while loop takes me out and script stops.
if anyone can help then it will be great if any new way plz also let me know Thanks in advance
I suppose, following the code snippet, that the problem in the String [] b = a[a.length-1].split("//]"); line. You probably receive 0 from a.length and this goes to the exception. Could you please add print variable a before this line?
Also if this is not the problem, could you please add full exception stack to the post?

InputStream read is blocked while reading BLOB from Oracle column through JDBC

While trying to read from an InputStream obtained from a BLOB like below code, the InputStream goes to indefinite wait state.
I set this data from a web application running on Jboss app server and read/write works absolutely fine, problem is while running a standalone java code using plain JDBC.
Environment is JDK6, Oracle 10g.
ResultSet rs = this.stmt.executeQuery();
log.println("ResultSetType: " + (rs != null ? rs.getClass() : null));
while (rs != null && rs.next()) {
. . . // read other columns
Blob savedBlob = rs.getBlob("PERSISTENCE_BLOB");
long len = savedBlob.length();
log.println("Going to read bytes..." + len);
InputStream is = savedBlob.getBinaryStream();
log.println("IS Received...");
log.println("Available : " + is.available());
ObjectInputStream oip = new ObjectInputStream(is);
Object obj = oip.readObject();
oip.close();
is.close();
savedBlob.free();
. . .
Output is as Below...
ResultSetType: class oracle.jdbc.driver.OracleResultSetImpl
RowID: XXXXXXXXXXXXXXX // Row is selected and printed properly
Going to read bytes...6022
IS Received...
Available : 0
But if i try to read as below in chucks.. it works fine, which i don't want as i am reading a serialized object and want to have ObjectInputStream opend from InputStream.
. . .
ResultSet rs = this.stmt.executeQuery();
log.println("ResultSetType: " + (rs != null ? rs.getClass() : null));
while (rs != null && rs.next()) {
. . .
Blob savedBlob = rs.getBlob("PERSISTENCE_BLOB");
long len = savedBlob.length();
int start = 1;
int totalBytesRead = 0;
int buffSize = 2048;
byte[] byteBuff = null;
log.println("Going to read bytes..." + len);
do {
byteBuff = new byte[buffSize];
byteBuff = savedBlob.getBytes(start, buffSize);
totalBytesRead += buffSize;
log.println(start + "," + buffSize + " #BLOB bytes: " + new String(byteBuff));
start += buffSize;
. . .
} while (. . . );
log.println("Total Bytes: " + totalBytesRead);
Output:
ResultSetType: class oracle.jdbc.driver.OracleResultSetImpl
Going to read bytes...6022
1,2048 #BLOB bytes: //......bytes data..........
.....
Total Bytes: 6022
InputStream.available() doesn't indicate how much you can read, it indicates how much it can return to you (eg from a buffer), without going into a - potentially - blocking read operation.
The Javadoc also indicates:
Note that while some implementations of InputStream will return the
total number of bytes in the stream, many will not. It is never
correct to use the return value of this method to allocate a buffer
intended to hold all data in this stream.
and
The available method for class InputStream always returns 0.
So instead of using available() as any sort of indication, just read it (which clearly works as indicated by your other code).

Creating a unique filename from a list of alphanumeric strings

I apologize for creating a similar thread to many that are out there now, but I mainly wanted to also get some insight on some methods.
I have a list of Strings (could be just 1 or over a 1000)
Format = XXX-XXXXX-XX where each one is alphanumeric
I am trying to generate a unique string (currently 18 in length but probably could be longer ensuring not to maximize file length or path length) that I could reproduce if I have that same list. Order doesn't matter; although I may be interested if its easier to restrict the order as well.
My current Java code is follows (which failed today, hence why I am here):
public String createOutputFileName(ArrayList alInput, EnumFPFunction efpf, boolean pHeaders) {
/* create file name based on input list */
String sFileName = "";
long partNum = 0;
for (String sGPN : alInput) {
sGPN = sGPN.replaceAll("-", ""); //remove dashes
partNum += Long.parseLong(sGPN, 36); //(base 36)
}
sFileName = Long.toString(partNum);
if (sFileName.length() > 19) {
sFileName.substring(0, 18); //Max length of 19
}
return alInput;
}
So obviously just adding them did not work out so well I found out (also think I should take last 18 digits and not first 18)
Are there any good methods out there (possibly CRC related) that would work?
To assist with my key creation:
The first 3 characters are almost always numeric and would probably have many duplicate (out of 100, there may only be 10 different starting numbers)
These characters are not allowed - I,O
There will never be a character then a number in the last two alphachar subset.
I would use the system time. Here's how you might do it in Java:
public String createOutputFileName() {
long mills = System.currentTimeMillis();
long nanos = System.nanoTime();
return mills + " " + nanos;
}
If you want to add some information about the items and their part numbers, you can, of course!
======== EDIT: "What do I mean by batch object" =========
class Batch {
ArrayList<Item> itemsToProcess;
String inputFilename; // input to external process
boolean processingFinished;
public Batch(ArrayList<Item> itemsToProcess) {
this.itemsToProcess = itemsToProcess;
inputFilename = null;
processingFinished = false;
}
public void processWithExternal() {
if(inputFilename != null || processingFinished) {
throw new IllegalStateException("Cannot initiate process more than once!");
}
String base = System.currentTimeMillis() + " " + System.nanoTime();
this.inputFilename = base + "_input";
writeItemsToFile();
// however you build your process, do it here
Process p = new ProcessBuilder("myProcess","myargs", inputFilename);
p.start();
p.waitFor();
processingFinished = true;
}
private void writeItemsToFile() {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(inputFilename)));
int flushcount = 0;
for(Item item : itemsToProcess) {
String output = item.getFileRepresentation();
out.println(output);
if(++flushcount % 10 == 0) out.flush();
}
out.flush();
out.close();
}
}
In addition to GlowCoder's response, I have thought of another "decent one" that would work.
Instead of just adding the list in base 36, I would do two separate things to the same list.
In this case, since there is no way for negative or decimal numbers, adding every number and multiplying every number separately and concatenating these base36 number strings isn't a bad way either.
In my case, I would take the last nine digits of the added number and last nine of the multiplied number. This would eliminate my previous errors and make it quite robust. It obviously is still possible for errors once overflow starts occurring, but could also work in this case. Extending the allowable string length would make it more robust as well.
Sample code:
public String createOutputFileName(ArrayList alInput, EnumFPFunction efpf, boolean pHeaders) {
/* create file name based on input list */
String sFileName1 = "";
String sFileName2 = "";
long partNum1 = 0; // Starting point for addition
long partNum2 = 1; // Starting point for multiplication
for (String sGPN : alInput) {
//remove dashes
sGPN = sGPN.replaceAll("-", "");
partNum1 += Long.parseLong(sGPN, 36); //(base 36)
partNum2 *= Long.parseLong(sGPN, 36); //(base 36)
}
// Initial strings
sFileName1 = "000000000" + Long.toString(partNum1, 36); // base 36
sFileName2 = "000000000" + Long.toString(partNum2, 36); // base 36
// Cropped strings
sFileName1 = sFileName1.substring(sFileName1.length()-9, sFileName1.length());
sFileName2 = sFileName2.substring(sFileName2.length()-9, sFileName2.length());
return sFileName1 + sFileName2;
}

Resources