Sunday, December 16, 2012

An effective solution to "java.sql.SQLException: [SQLITE_BUSY] The database file is locked (database is locked)"

Similar to links like:

http://stackoverflow.com/questions/7930139/android-database-locked
http://stackoverflow.com/questions/13891006/getting-sqlite-busy-database-file-is-locked-with-select-statements

The sqlite database is sometimes locked very long when trying to insert, delete or update data with a java program. I had read the posts above but found no definite and clear solution in these  answers. I had also tried the proposed solution shown in the video https://www.youtube.com/watch?v=o7dn0cLvb5o about "the database is locked problem" in vain.


But finally, I figured out a simple and effective way to circumvent this problem so that I can continue my coding. The solution is as follows:


1.Backup the database folder where the locked sqlite db is located.





 2. Use Unlocker to delete the locked .db file




Unlocker can be downloaded from 
http://www.emptyloop.com/unlocker/Unlocker1.9.1-x64.exe
in the webpage
http://www.emptyloop.com/unlocker/

3.Copy the backup .db file back to the directory of the deleted locked sqlite .db.



These three simple steps can effectively solve the problem of  "java.sql.SQLException: [SQLITE_BUSY]  The database file is locked (database is locked)." Try it to evade this problem if baffled by it for quite a long time.


Saturday, November 24, 2012

Way to solve "could not create audio stream from input stream"


Similar to this link,

http://www.javaprogrammingforums.com/whats-wrong-my-code/9116-could-not-create-audio-stream-input-stream.html

I was also once confronted with the problem of "could not create audio stream from input stream"
"Exception in thread "main" java.io.IOException: could not create audio stream from input stream"
when trying to use TTS api of some website and playing the recorded .wav file.

After searching on the Internet for quite much time, I ultimately found out the way to solve this problem, which is as follows:

1.Download jl1.0.jar, jmf.jar, and mp3plugin.jar.

2.Copy the jar files to a folder like lib inside the java project.

3.Go to Configure Build Path→Libraries→Add Jars to add these jars.


With these steps, the problem is solved.


The reason behind this IOException is probably related to the file format. A .wav file may be encoded with an mp3 codec.

Tuesday, February 28, 2012

具加減功能的簡易Java GUI計算機

 
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class calculate extends JFrame {

 private JPanel contentPane;
 private JTextField textFieldForexpression; 
 private JButton btnEnter = new JButton();
 private JLabel lblInput = new JLabel("Please input the math expression");
 
 public calculate()
 {
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  setBounds(100, 100, 700, 500);
  contentPane = new JPanel();
  contentPane.setBackground(new Color(238, 238, 209 ));
  contentPane.setBorder(BorderFactory.createEtchedBorder(Color.red, Color.darkGray));
  contentPane.setLayout(null);
  setContentPane(contentPane);
  
  textFieldForexpression = new JTextField();
  textFieldForexpression.setBounds(200, 200, 300, 30);
  textFieldForexpression.setVisible(true);
  contentPane.add(textFieldForexpression);
  
  btnEnter.setHorizontalAlignment(SwingConstants.CENTER);
  btnEnter.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent arg0) 
   {
    if (!hasInputError())
     JOptionPane.showMessageDialog(null, "請輸入正確的算式");
    else
    { 
     if (getAnswer() == Float.MAX_VALUE)
      return;
     int i = (int) getAnswer();
     if ( getAnswer() == (int) getAnswer())
      JOptionPane.showMessageDialog(null, "答案是: "  + i);
     else
      JOptionPane.showMessageDialog(null, "答案是: "  + getAnswer());
    }
   }
  });
  btnEnter.setBounds(300, 300, 100, 40);
  btnEnter.setText("Enter");
  btnEnter.setVisible(true);
  btnEnter.setForeground(Color.blue);
  btnEnter.setFont(new Font("Vrinda", Font.BOLD, 20));
  contentPane.add(btnEnter);
  
  lblInput.setFont(new Font("Aparajita", Font.BOLD, 24));
  lblInput.setBounds(150, 80, 400, 35);
  lblInput.setHorizontalAlignment(JLabel.CENTER);
  lblInput.setVisible(true);
  lblInput.setForeground(new Color(255, 71, 0));
  contentPane.add(lblInput);
 } //end of calculate()
 
 public boolean isFloat(String str)
 {
  try {
   Float.parseFloat(str);
   return true;
  }   catch (NumberFormatException e) {
   return false;
  }
 } //end of boolean isFloat(String str)
 
 public boolean hasInputError()
 {
  String s = textFieldForexpression.getText();
  if (s.length() == 0)
   return false;
  else
  for (int i = 0; i < s.length() - 1; i ++ )
  {
   if ((s.charAt(i) == '+' || s.charAt(i) == '-') && (s.charAt(i + 1) == '+' || s.charAt(i + 1) == '-'))
    return false;
   else if( (s.charAt(i) >= '0' && s.charAt(i) <= '9') ||
     s.charAt(i) == '+' || s.charAt(i) == '-' || s.charAt(i) == '.' );
   else
    return false;
  }
  if ( !(s.charAt(s.length() - 1) >= '0' && s.charAt(s.length() - 1) <= '9'))
   return false;
  return true;
 }  //end of boolean hasInputError()
 
 public float getAnswer()
 {
  int previousJiaJianIndex = 0;
  String s = textFieldForexpression.getText();
  float result = 0;
  
  int i;
  for ( i = 1; i < s.length(); i ++)
  {
   if (s.charAt(i) == '+' || s.charAt(i) == '-')
   { 
    if (isFloat(s.substring(previousJiaJianIndex, i)))
     result += Float.parseFloat(s.substring(previousJiaJianIndex, i));
    else
    { 
     JOptionPane.showMessageDialog(null, "請輸入正確的算式");
     return Float.MAX_VALUE;
    }
    previousJiaJianIndex = i; 
   }
  }
  
  if (previousJiaJianIndex == 0)
  { 
   JOptionPane.showMessageDialog(null, "請輸入正確的算式");
   return Float.MAX_VALUE;
  }
  else
   return result + Float.parseFloat(s.substring(previousJiaJianIndex, i));
 } //end of float getAnswer()

 public static void main(String args[]) {

  EventQueue.invokeLater(new Runnable() {
   public void run() {
    try {
     calculate frame = new calculate();
     frame.setVisible(true);
    } catch (Exception e) {
     e.printStackTrace();
    }
   }
  });
 } //end of static void main
 
}

Friday, January 13, 2012

利用C語言寫出長整數2進位轉10進位

 
#include "stdio.h"
#define size 128

//sum[0]視為第0位, sum[1]第1位 依此類推
//例如若這陣列記14547,則sum[4] ~ sum[0]分別是1,4,5,4,7
int sum[size] = {0};

void Double()
{
 //就是把sum陣列這個長整數的值加倍,我的算法是自己加自己

 int i;
 int carry = 0; //代表有進位

 for (i = 0; i < size; i ++)
 {
  //i = 0 時,carry為0,因為第一位不會有進位
  //i > 0 時,carry 值為
  //當sum[i-1]+sum[i-1]加前一個carry>=10時就設為1,不是則為0
  //例如計算38+38,sum[0]的值為先算完sum[0]+sum[0]=16,
  //而16>10,所以設carry = 1及sum[0] = 16-10 = 6
  //接著sum[1]的值為sum[1]+sum[1]+carry = 3 + 3 + 1 = 7

  sum[i] = sum[i] + sum[i] + carry; 

  if (sum[i] >= 10)
  {
   //若這位數的和大於等於10,代表有進位,
   //這一位要減10,而下一位要多加1,
   carry = 1;
   sum[i] -= 10 ;
  }
  else
   carry = 0;
 }
}

void Add1()
{
 //就是把sum陣列的值 + 1,
 //例如136變137,其中sum[2] = 1, sum[1] = 3, sum[0] = 6,
 //變sum[2] = 1, sum[1] = 3, sum[0] = 7
 //或39變40,其中sum[1] = 3, sum[0] = 9,
 //變sum[1] = 4, sum[0] = 0

 int i = 0;
 int carry = 0;
 
 sum[0] ++;
 if ( sum[0] == 10)
 {
  //加1後若有進位,則只可能是10
  //於是carry為1,sum[0]值就為尾數0,
  carry = 1;
  sum[0] = 0;
 }

 //若carry不是1,則結尾加1後,就完成了加1;
 //是的話,則要從第二位起繼續加。例如99+1=100,sum[1]和sum[2]也跟著變
 while ( carry == 1)
 { 
  //遇到結尾是9, 99, 或9999...時,才會跑進這while
  i++;  //代表再走到下一位
  sum[i] ++; //表示這一位多加carry值1,所以sum[i]++
  if (sum[i] == 10)
  {
   //若還繼續進位的話,就會繼續維持carry = 1,sum[i]這位則變為9+1-10=0
   sum[i] = 0;
  }
  else
   break;  //表示沒繼續進位,也完成了這個數加1
 }

}


int main()
{
 int i;
 char str[size];
 int weisu;

 printf("請輸入二進位數字字串(例如01001)\n");
 scanf("%[0-1]", str); //也可把[0-1]改成d


 for (i = 0 ; i < size ; i++)
 {
  if (str[i] == '\0')
   break;

  Double(); //把sum陣列的值加倍

  if (str[i] == '1') 
   Add1();  //是1的話就多加1,不是的話就不用
 }


 //weisu代表sum陣列代表的數的最高位。
 //例如若輸入為11001,sum代表值就會是25 (sum[1] = 2, sum[0] = 5),
 //而weisu 會等於 1

 weisu = size - 1; 
 
 //從size-1位開始,找到真正的weisu
 //例如sum陣列從最高位起為00...0015,
 //就從最高位起開始找,直到遇到的第一個不是0的位數時停下來
 //此處就代表sum的weisu
 while (sum[weisu] == 0 && weisu >= 0)
  weisu--;

 printf("這個二進位數字的十進位為:");

 if (weisu == -1)
  printf("0\n"); //沒有sum[-1],但若遇到weisu = -1則sum代表的值必是0
 else
 {
  //從最高位印到第0位
  for (i = weisu; i >= 0 ; i --)
   printf("%d", sum[i]);

  printf("\n");

 }


 system("pause");
 return 0;
}

Monday, January 9, 2012

C++的getline與以strtok作字串分割

以下程式可以以getline輸入加法的字串,例如"1.1 + 2 + 3.5 + 4",輸出為這幾個數的和。方法就是以strtok分割字串,然後以atof轉成數值,然後把值將加後,最後得到結果
 
#include "iostream"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"

using namespace std;

int main()
{
 char str[256];

 cout << "請輸入加法運算字串,例如1.1 + 2 + 3.5 + 4 : \n";
 cin.getline(str, 100);

 char *delim = "+";
 char * pch;
 int i = 0, j;
 double answer = 0;
 double values[4];

 pch = strtok(str, delim);

 while (pch != NULL)
 {
  values[i] = atof(pch);
  cout << "values[i] = " << values[i] << endl;
  pch = strtok(NULL, delim);
  i++;
 }

 for ( j = 0 ; j < i ; j ++)
  answer = answer + values[j];

 cout << "這" << i << "個數的和為" << answer << endl;

 system("pause");
 return 0;
}

Sunday, January 8, 2012

以Prim's Algorithm來求最小成本擴張樹

 
 #include "stdafx.h"
#include <iostream>
#include <stdio.h>
#define INF 10000000

using namespace std;

//一個undirected graph的adjacency matrix
int adjMatrix[8][8] =
{
 {0, 300, 1000, INF, INF, INF, INF, 1700},
 {300, 0, 800, INF, INF, INF, INF, INF},
 {1000, 800, 0, 1200, INF, INF, INF, INF},
 {INF, INF, 1200, 0, 1500, 1000, INF, INF},
 {INF, INF, INF, 1500, 0, 250, INF, INF},
 {INF, INF, INF, 1000, 250, 0, 900, 1400},
 {INF, INF, INF, INF, INF, 900, 0, 1000},
 {1700, INF, INF, INF, INF, 1400, 1000, 0},
 
};

int addedVertices[8] = {0};
int addedVerticesNum = 1;       //紀錄成為spanning tree的各邊中其中一點的數目數目。第一個點為0

bool isAdded(int v)
{
 //檢驗這個點是不是已被加入spanning tree的邊中其中一個點

 for (int i = 0 ; i < addedVerticesNum; i ++)
 {
  if (addedVertices[i] == v)
   return true;
 }

 return false;
}


//紀錄會成為spanning tree的7條邊。若頂點數目是n則是n-1條邊
struct Edge
{
 int node1;
 int node2;

} edge[7];


int main(int argc, char* argv[])
{

 int p1, p2;   //紀錄被檢驗的邊的兩點
 int lowestWeight; //在下面的三層迴圈中,暫存與已被加入spanning tree的邊相連的邊中,weight最低的
 int thep1, thep2; //紀錄這一次要被加入minimum cost spanning tree的邊的兩個頂點  
  
 
 for (int i = 0 ; i < 8 ; i ++)
 { 
  lowestWeight = INF;

  for (int count = 0; count < addedVerticesNum; count++)
  {
   //從幾個已被加的點開始找
   p1 = addedVertices[count];

   for (p2 = 0; p2 < 8 ; p2++)
   {
    if ( p2 != p1 && adjMatrix[p1][p2] < lowestWeight && !isAdded(p2) )
    { 
     //這個要被加入spanninf tree的邊的兩個點不同,所以 p2 != p1
     //兩個點之間須有邊相連,所以 adjMatrix[p1][p2] < INF。
     //adjMatrix[p1][p2] < lowestWeight則是為了找出權重最低的邊
     //在加一條新的邊時,依prim的演算法必須一點是已被加入spanning tree的邊中的其中一點,另一點不是。
     //而p1 = addedVertices[count] 和 !isAdded(p2)代表p1是其中一點,p2不是

     lowestWeight = adjMatrix[p1][p2];
     thep1 = p1;
     thep2 = p2;
    } 
   }


  }
  

  if (lowestWeight < INF)
  {
   edge[addedVerticesNum - 1].node1 = thep1;
   edge[addedVerticesNum - 1].node2 = thep2;
   //thep1是新加入spanning tree的邊中,已和其中一條被加入spanning tree的邊相連的點,
   //thep2則是尚未與被加入spanning tree的邊相連的另一點

   addedVertices[addedVerticesNum] = thep2; 
   addedVerticesNum++;
  }
  else //若lowestWeight = INF,表示p1未與其他任何點相連,所以整個圖必定沒有spanning tree
   break;
   
 }
  
  
 

 if (addedVerticesNum < 8 )
  cout << "No spanning tree\n";
 else
 {
  cout << "The edges of the spanning tree are:\n";

  for (int i = 0 ; i < 7; i++ )
   cout << "edge " << edge[i].node1 << edge[i].node2 << endl;
 
 }

 //以文章最上面的圖為例,就會輸出
 //the edges of the spanning tree are:
 //edge 01
 //edge 12
 //edge 23
 //edge 35
 //edge 54
 //edge 56
 //edge 67


 system("PAUSE");
 return 0;
}
 

Monday, January 2, 2012

C++ 二元樹的刪除節點


#include "stdafx.h"
#include <iostream>
#include <stdlib.h>

using namespace std;

struct node
{
    int data;
    struct node *left;    // self-reference linker
    struct node *right;    // self-reference linker

} *root, *tree, *t;



struct node *GetSmallest(struct node *ptr)
{
     while (ptr->left != NULL)
           ptr=ptr->left;

     return ptr;
}


struct node *Delete(struct node *ptr, int value)
{
     //從維基百科知,There are three possible cases to consider:
     //   1. Deleting a leaf (node with no children): Deleting a leaf is easy, as we can simply remove it from the tree.
     //   2. Deleting a node with one child: Remove the node and replace it with its child.
     //   3. Deleting a node with two children: Call the node to be deleted N. Do not delete N.
     //  Instead, choose either its in-order successor node or its in-order predecessor node, R.
     //         Replace the value of N with the value of R, then delete R.

     //第一和和第二種情形的刪除很容易,第種情形時的刪除,我是用「中序立即後繼節點(inorder immediate successor)」法,
     //就是將欲刪除節點的右子樹最小者向上提。詳細可參閱網路上搜尋的介紹
    
    
     struct node *temp;


     if (ptr!= NULL)
     {
           ////第一種情形
           if (ptr->right == NULL && ptr->left == NULL)
                ptr= NULL;
           ///////////
           //第二種情形
           else if (ptr->left == NULL)
                ptr = ptr->right;
           else if (ptr->right == NULL)
                ptr = ptr->left;
           //////////
           else if (value > ptr->data)
                ptr->right = Delete(ptr->right, value);
           else if (value < ptr->data)
                ptr->left = Delete(ptr->left, value);

           ////////
           //第三種情形
           else
           {
                temp = GetSmallest(ptr->right);
                temp->left = ptr->left;
                ptr = ptr->right;

           }
           /////////

     }
     else
           cout << "Sorry, the input does not match any node's value in the tree.\n";

     return ptr;
}



int main(int argc, char* argv[])
{
    int i, key;

    root = NULL;

    for (i = 0; i < 6; i++)
    {
           cout << "Enter number " << i+1 << " > " ;

           cin >> key;
           if (root == NULL)   // 插入第一個數字
           {
                root = new struct node;
                root->data = key;
                root->left = root->right = NULL;
           }
           else  // 插入第二個以後的數字
           {
                tree = root;
                while (tree != NULL)
                {
                     if (key == tree->data)  // 要插入的數字已經存在於樹中
                     {
                           cout << "duplicate node!";
                           break;
                     }
                     else if (key < tree->data)   // 要插入的數字< 節點數字, 向左子樹移動
                     {
                           if (tree->left != NULL)
                                tree = tree->left; // 向左子樹移動
                           else // 沒有左子樹時, 則新增節點, 放置要插入的數字
                           {
                                t = new struct node;
                                t->data = key;
                                t->left = t->right = NULL;
                                tree->left = t;
                                break;
                           }
                     }
                     else // 要插入的數字> 節點數字, 向右子樹移動
                     {
                           if (tree->right != NULL)
                                tree = tree->right; // 向右子樹移動
                           else // 沒有右子樹時, 則新增節點, 放置要插入的數字
                           {
                                t = new struct node;
                                t->data = key;
                                t->left = t->right = NULL;
                                tree->right = t;
                                break;
                           }
                     }
                }
           }
     }

     cout << "root->left->left->data = " << root->left->left->data << endl;
     Delete(root, 0);

     cout << "root->left->data = " << root->left->data << endl;

     if (root->left->left == NULL)
           cout << "root->left->left == NULL";

     //例如插入3 1 4 0 2 5 ,經Delete(root, 0)後,就會發現被刪掉了

     system("pause");
    return 0; // 設置中斷點, 察看樹的形狀
}