Sqlite real data invalid(cannot reproduce) - android

I have text file and I convert it to insert query with transaction (thousands record).
The insert query I used is wrap with transaction like this.
public static void bulkInsert(DatabaseWrapper db, String tableName, String[] columns, String[][] values){
StringBuilder stringBuilder = new StringBuilder();
int index = 0;
String head = "INSERT OR REPLACE INTO " + tableName + " (" + TextUtils.join(",", columns) + ") VALUES ";
while (index < values.length) {
stringBuilder.setLength(0);
stringBuilder.append(head);
for (int i = 0; i < 500; i++) {
if (index < values.length) {
if (i != 0) stringBuilder.append(",");
stringBuilder.append("(").append(TextUtils.join(",",values[index])).append(")");
} else {
break;
}
index++;
}
db.execSQL(stringBuilder.toString());
}
}
then I found that single record out of 3964 records that has real value from 10.86 become 1.95223612752995e-314 but the others look fine.
I have no clue what happen here.
Edited1
Example of text file are like this
1004500803 KH1 001 P01 344 8850123136016 0000 0000010.86 00000 00000
0054 30082017080
1004500803 KH1 001 P01 345 8850123136023 0000 0000010.86 00000 00000
0055 30082017077
1004500803 KH1 001 P01 199 8850123123337 0001 0000007.24 00000 00000
0061 30082017081
1004500803 KH1 001 P01 032 8850123130410 0000 0000010.86 00000 00000
0065 30082017074
1004500803 KH1 001 P01 383 8850123135040 0001 0000010.86 00000 00000
0071 30082017074
each position of text data are fix in code so decided to convert column name and value into array of string
String[][] fileValues;
fileValues = PRS.getValueArrays();
public String[][] getValueArrays() {
try {
File file = new File(Constant.Path.MASTER_FILE_PATH, getFileName());
List<String[]> list = new ArrayList<>();
if (file.exists()) {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "TIS-620"));
String line;
while ((line = br.readLine()) != null && !line.isEmpty() && !line.contains("EOF")) {
String[] valueArray = new String[fileIndex.length];
for (int i = 0; i < fileIndex.length - 1; i++) {
valueArray[i] = line.substring(fileIndex[i], fileIndex[i + 1]).trim();
}
valueArray[fileIndex.length - 1] = line.substring(fileIndex[fileIndex.length - 1], lineLength).trim();
list.add(valueArray);
}
br.close();
String[][] valueList = new String[list.size()][];
return list.toArray(valueList);
}
} catch (IOException | NullPointerException e) {
e.printStackTrace();
}
return null;
}
and this is function i parse text file to string arrays (may have some business logic)
public static String[][] parsePrsFileToPresaleValues(String[][] fileValue) {
String[][] result = new String[fileValue.length][];
sumRawPrice = 0;
for (int i = 0; i < fileValue.length; i++) {
String[] fromFile = fileValue[i];
double price = Double.parseDouble(fromFile[7]);
sumRawPrice += price;
result[i] = getPresaleValue(
fromFile[0],
fromFile[5],
Integer.parseInt(fromFile[6]),
fromFile[8].equals("00000") ? 9999 : fromFile[8].equals("99999") ? 0 : Integer.parseInt(fromFile[8]),
fromFile[9].equals("99999") ? 9999 : fromFile[9].equals("00000") ? 0 : Integer.parseInt(fromFile[9]),
price
);
}
return result;
}
and call bulk insert like this
public static void insertData(DatabaseWrapper db) {
db.beginTransaction();
DbUtil.bulkInsert(db, Presale.NAME, Presale.INSERT_COLUMN, Presale.parsePrsFileToPresaleValues(fileValues));
db.setTransactionSuccessful();
db.endTransaction();
}
this is the result of insert statement string
INSERT OR REPLACE INTO price_methods (code,item_code,promotion_code,price,created_at,updated_at) VALUES ('KB0','8850123110108','000',24.67,1503503909093,1503503909093),('KB0','8850123110115','000',12.71,1503503909101,1503503909101)
Edited2
By the way it's not happen all the time.
This app running like two years and insert data like this about 10k record per day and work fine until this happened

The internal representation of your value has some variance because it can't be represented exactly as a binary floating point number. This is especially a problem if you are casting it between double/float etc.
You haven't posted all of your code so firstly make sure you use the correct column type that suits your usage. Also consider using BigDecimal within your application to take advantage of methods such as its scaling

Related

Why when reading NFCtag with Android phone you get different tag ID then when reading with dedicated reader?

I am using an Android Cilico F750 and the dedicated RFID reader is CF-RS103.
The RFID tag type is MIFARE Ultralight type C.
When read with a dedicated card reader the id of tag is: 2054270212(10 digit).
But when read with Android phone the id is: 36139312876727556(17digit) and reversed id is: 1316602805183616 (16digit).
Does anyone know why this happens and if its possible to convert the 10digit id to 17digit id or vice versa.
I use intents to detect tag and to resolve intent I use this:
public void resolveIntent(Intent intent){
String action = intent.getAction();
if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
||NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
||NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action))
{
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage[] msgs;
if(rawMsgs!=null)
{
msgs= new NdefMessage[rawMsgs.length];
for(int i=0; i<rawMsgs.length; i++)
{
msgs[i]=(NdefMessage) rawMsgs[i];
}
}
else
{
byte[] empty = new byte[0];
byte[] id = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
Tag tag = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
byte[] payload = dumpTagData(tag).getBytes();
NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN,empty,id,payload);
NdefMessage msg = new NdefMessage(new NdefRecord[]{record});
msgs= new NdefMessage[] {msg};
}
displayMsgs(msgs);
}}
And this are my helper functions:
private void displayMsgs(NdefMessage[] msgs)
{
if(msgs==null || msgs.length==0) {
return;
}
StringBuilder builder = new StringBuilder();
List<ParsedNdefRecord> records= NdefMessageParser.parse(msgs[0]);
final int size = records.size();
for(int i=0;i<size;i++)
{
ParsedNdefRecord record = records.get(i);
String str = record.str();
builder.append(str).append("\n");
}
text.setText(builder.toString());
}
private String dumpTagData(Tag tag) {
StringBuilder sb = new StringBuilder();
byte[] id = tag.getId();
sb.append("ID (hex): ").append(toHex(id)).append('\n');
sb.append("ID (reversed hex):").append(toReversedHex(id)).append('\n');
sb.append("ID (dec): ").append(toDec(id)).append('\n');
sb.append("ID (reversed dec):").append(toReversedDec(id)).append('\n');
String prefix = "android.nfc.tech.";
sb.append("Technologies: ");
for (String tech: tag.getTechList()) {
sb.append(tech.substring(prefix.length()));
sb.append(", ");
}
sb.delete(sb.length() - 2, sb.length());
for (String tech: tag.getTechList()) {
if (tech.equals(MifareClassic.class.getName())) {
sb.append('\n');
String type = "Unknown";
try {
MifareClassic mifareTag = MifareClassic.get(tag);
switch (mifareTag.getType()) {
case MifareClassic.TYPE_CLASSIC:
type = "Classic";
break;
case MifareClassic.TYPE_PLUS:
type = "Plus";
break;
case MifareClassic.TYPE_PRO:
type = "Pro";
break;
}
sb.append("Mifare Classic type: ");
sb.append(type);
sb.append('\n');
sb.append("Mifare size: ");
sb.append(mifareTag.getSize() + " bytes");
sb.append('\n');
sb.append("Mifare sectors: ");
sb.append(mifareTag.getSectorCount());
sb.append('\n');
sb.append("Mifare blocks: ");
sb.append(mifareTag.getBlockCount());
} catch (Exception e) {
sb.append("Mifare classic error: " + e.getMessage());
}
}
if (tech.equals(MifareUltralight.class.getName())) {
sb.append('\n');
MifareUltralight mifareUlTag = MifareUltralight.get(tag);
String type = "Unknown";
switch (mifareUlTag.getType()) {
case MifareUltralight.TYPE_ULTRALIGHT:
type = "Ultralight";
break;
case MifareUltralight.TYPE_ULTRALIGHT_C:
type = "Ultralight C";
break;
}
sb.append("Mifare Ultralight type: ");
sb.append(type);
}
}
return sb.toString();
}
private String toHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = bytes.length - 1; i >= 0; --i) {
int b = bytes[i] & 0xff;
if (b < 0x10)
sb.append('0');
sb.append(Integer.toHexString(b));
if (i > 0) {
sb.append(" ");
}
}
return sb.toString();
}
private String toReversedHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; ++i) {
if (i > 0) {
sb.append(" ");
}
int b = bytes[i] & 0xff;
if (b < 0x10)
sb.append('0');
sb.append(Integer.toHexString(b));
}
return sb.toString();
}
private long toDec(byte[] bytes) {
long result = 0;
long factor = 1;
for (int i = 0; i < bytes.length; ++i) {
long value = bytes[i] & 0xffl;
result += value * factor;
factor *= 256l;
}
return result;
}
private long toReversedDec(byte[] bytes) {
long result = 0;
long factor = 1;
for (int i = bytes.length - 1; i >= 0; --i) {
long value = bytes[i] & 0xffl;
result += value * factor;
factor *= 256l;
}
return result;
}`
EDIT: I managed to resolve this issue by truncating the 7-byte HEX ID to 4-bytes.
And then formating the decimal ID if its total lenght is less than 10 digits with this statement that basically adds zeroes from left side if DEC ID is smaller than 10 digits:
String strFinal=String.format("%010d", Long.parseLong(str));
This document that describes how the ID is converted from HEX8 TO DEC10 helped me alot aswell: https://www.batag.com/download/rfidreader/LF/RAD-A200-R00-125kHz.8H10D.EM.V1.1.pdf
And a huge thanks to #Andrew and #Karam for helping me resolve this!
The card reader on the PC is configured wrong, it is configured by default to display the ID as 10 digit decimal number (4 byte) when the card has a 7 byte ID.
It thus has to loose some data, it is doing this by truncating the ID to the first 4 bytes of the 7 byte ID
Use the software on the PC change the output format to something suitable for the ID size on the Mifare Ultralight C cards (8 Hex?)
or
Use Mifare Classic cards instead as these had 4 byte ID
or
truncate the 7 byte ID to 4 bytes e.g. change bytes.length to 4 (a hard coding to the first 4 bytes in the 7 byte ID) in your code and handle the fact that there is a very large number (around 16.7 million) of Mifare Ultralight C cards that will seem to have the same "ID" as you want to display it
This is because the spec's give by a seller on Amazon https://www.amazon.co.uk/Chafon-CF-RS103-Multiple-Support-Compatible-Black/dp/B017VXVZ66 (I cannot find any details on the manufacturer's site)
It says "Default output 10 digit Dec, control output format through software. "
"Support with windows,linux and android system, but can only set output format in windows pcs.No programming and software required, just plug and play. "
The only sensible answer is move everything to use a 7 byte ID.
I don't know why are you trying always to convert to decimal?
and please try to explain more about the code you use to read the UID.
about your numbers and to convert 17 digits to 10 digits; I convert both of them to Hex:
36139312876727556(17digit) in Hex : 8064837A71AD04.
2054270212(10 digit) in Hex: 7A71AD04
as you notice you can just tirm first three bytes to get the 10 digits.
and I do belive the both of them are not the UID. but the 7bytes as sayed Andrew, and you already read it in the your photo : (04:B5:71:7A:83:64:80)
So I think the answer is that because you are converting a 7 byte ID to decimal you are getting variable lengths of numbers because of the conversion to decimal.
"The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive)."
From https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
Could generate a decimal number with 1,2 or 3 characters thus as decimal the id can vary in length.
It also looks like that conversion is going wrong as in theory it should have negative numbers in there as well.
It is much better to handle it as a hex string if you want it to be human readable.
The correct method in Java to convert the 2 pages of the ID to hex is
StringBuilder Uid;
for (int i = 0; i < result.length; i++) {
// byte 4 is a check byte
if (i == 3) continue;
Uid.append(String.format("%02X ", result[i]));
}
Note as per the spec sheet of the card https://www.nxp.com/docs/en/data-sheet/MF0ICU2_SDS.pdf (Section 7.3.1)
There is check byte that is part of the ID, while this will always be the same on the same card and will still give you a unique ID it is technically not part of the ID.
Or if not reading at a low level then
https://developer.android.com/reference/android/nfc/Tag#getId()
will get you the id.
Note that the "36139312876727556(17digit) and reversed id" when converted to hex and reversed actual is 7 bytes and start with the right number.
The 10 digit just looks like the first 4 bytes of the 7 byte number also reversed.

how to get the indexes of all the occurences of words in string?

I want to get indexes of all the occurences of string_to_be_search
Input:
String line="hello this is prajakta , how are you?? hello this is prajakta!"
String text_to_search= "hello this is prajakta"
Here the occurrences of text_to_search is 2 so I need list of starting indexes
Output:
List l=[0,39]
Also I have tried a code below
public List getIndexesOfMultipleOccuredString(String originalString,String textToSearch) {
int i, last = 0, count = 0;
List l = new ArrayList();
do {
i = originalString.indexOf(textToSearch, last);
if (i != -1) l.add(i);
last = i + textToSearch.length();
} while (i != -1);
return l;
}
BUT
if my input is as follows
String line="hello this is prajakta ,i love to drive car and i am a carpainter"
String text_to_search="car"
Output:
It gives me two indexes as carpainter contains car which i don't want
Output should be [39]
This is how you do it using regex(word matching)
String line= "hello this is prajakta , how are you?? hello this is prajakta!";
String text_to_search = "\\bhello this is prajakta\\b";
ArrayList<Integer> list = new ArrayList<>();
Pattern p = Pattern.compile(text_to_search);
Matcher m = p.matcher(line);
while (m.find()) {
list.add(m.start());
}
Log.i("All occurrences", "values are " + list.toString());
Output: [0, 39]
If you search using these strings
String line="hello this is prajakta ,i love to drive car and i am a carpainter";
String text_to_search="car";// use as "\\bcar\\b"
Output [40]

how to loop through 2d array and make the result appear in table form in android

HI below is the code which gets the four columns data from the curson and put in the 2d array. basically there are two issues one is that i get the last value as nullnullnullnull means all for columns are fetched as null.
the seconds is that i want to print the array in multitextline or if any other widget availabe so that i get four fields in a row. like
id rule_body rule_con boole
0 abc def 1
0 a f 0
c.moveToFirst();
int i=0;
while(c.moveToNext()) {
String id = c.getString(c.getColumnIndex("id"));
String rb = c.getString(c.getColumnIndex("rule_body"));
String cn = c.getString(c.getColumnIndex("rule_cons"));
String bl = c.getString(c.getColumnIndex("boole"));
table[i][0] = id;
table[i][1] = rb;
table[i][2] = cn;
table[i][3] = bl;
++i;
}
for(int a=0;a<count_row;a++)
for(int b=0;b<count_col;b++) {
obj_ml.append(String.valueOf(table[a][b]));
}
so far i am getting all the result in a single line. any help will be appreciated.
Change your for-loop as below
for (int a=0;a<count_row;a++)
{
for(int b=0;b<count_col;b++)
{
obj_ml.append(String.valueOf(table[a][b]));
}
// add to obj_ml new line character '\n'
obj_ml.append("\n");
}

Splitting a string at n-th character with different length

i am trying to split string. I am using
for (String part : getParts(RESPONSE_STRING, 3)) {
// System.out.println(" MY STRING " + part);
partlist.add(part);
}
private static List<String> getParts(String string, int partitionSize) {
List<String> parts = new ArrayList<String>();
int len = string.length();
for (int i = 0; i < len; i += partitionSize) {
parts.add(string.substring(i, Math.min(len, i + partitionSize)));
}
return parts;
}
MY input is 0130010010102255051
output : 013 001 001 010 225 505 1
but i want my output
013 001 001 01 02 255 051
How do i achive this output ? Any idea of how to get my characters ? Many Thanks

Replacing part of String one by one

I have string:
Apple, Banana, Strawberry; Lemon, Watermelon; Orange
When I try this:
if(meaning.contains(";"))
{
meaning=meaning.replace(";", "\n");
}
Result:
Apple, Banana, Strawberry
Lemon, Watermelon
Orange
How to replace part of String one by one in order to replace ";" to "\n"+numStr?
1.Apple, Banana, Strawberry
2.Lemon, Watermelon
3.Orange
Didn't test it, but should work:
String[] lines = meaning.split(";");
StringBuilder res = new StringBuilder();
for (int i = 0, size = lines.length; i < size; i++) {
res.append(i + 1).append(". ").append(lines[i]).append("\n");
}
res.toString();
You can use the following code. The trick is to use String.split() instead of String.replace().
if(meaning.contains(";"))
{
StringBuilder builder = new StringBuilder();
String[] meanings = meaning.split(";");
for (int i = 0; i < meanings.length; i++) {
builder.append(String.format(Locale.US, "%d. %s\n", i, meanings[i].trim()));
}
Log.d("meanings", builder.toString());
}
The result will print:
1.Apple, Banana, Strawberry
2.Lemon, Watermelon
3.Orange

Categories

Resources