Android——数据存储(二)(二十二)

1. SQLite数据库存储

1.1 知识点

(1)了解SQLite数据库的基本作用;

(2)掌握数据库操作辅助类:SQLiteDatabase的使用;

(3)可以使用命令操作SQLite数据库;

(4)可以完成数据库的CRUD操作;

(5)掌握数据库查询及Cursor接口的使用。

1.2 具体内容

在Android当中,本身提供了一种微型的嵌入式数据库叫做SQLite,同样可以执行SQL语句,对于不熟悉sql和jdbc的小伙伴,还是需要去自学一下。

下面我们首先使用一段代码演示如何取得数据库表操作。

package com.example.sqliteopenhelper;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;public class MySQLiteOpenHelper extends SQLiteOpenHelper {public static final String DATABASENAME="wancy";//数据库名称public static final int DATABASEVERSION=1;//版本号public static final String TABLENAME = "DH10";//数据库表名public MySQLiteOpenHelper(Context context) {super(context, DATABASENAME, null, DATABASEVERSION);// TODO Auto-generated constructor stub}@Overridepublic void onCreate(SQLiteDatabase db) {String sql = "create table "+TABLENAME+" (id INTEGER PRIMARY KEY,"+"name VARCHAR(50) NOT NULL,"+"birthday DATE NOT NULL)";db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {String sql = "drop table if exists "+TABLENAME;//当退出的时候删除表db.execSQL(sql);this.onCreate(db);}}

以上要注意一点,在SQLite当中如果想要让某个字段自动增长,那么在创建表的时候使用“INTEGER PRIMARY KEY”声明即可。

那么这样的话一个数据库辅助类已经定义好了,那么我们下面在Activity当中去调用此类的方法。

package com.example.sqliteproject;import com.example.sqliteopenhelper.MySQLiteOpenHelper;import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;public class SQLiteActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_sqlite);MySQLiteOpenHelper helper = new MySQLiteOpenHelper(this);helper.getWritableDatabase();//表示以读写的形式打开数据库}}

现在已经取得了数据库的连接了,如果以上代码没有错误,运行之后就可以在文件列表当中找到数据表.FileExplorer/data/data/数据库辅助类所在的包/database。根据代码,可以发现,如果数据库不存在,那么会自动调用onCreate方法去创建表,如果数据库已经存在了,但是版本号发生了改变,将会调用onUpgrade方法,现将原来的表删除之后,在去创建新的表。

·使用SQLite数据库并完成数据库的更新操作。

public void insert(String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象String sql = "insert into "+TABLENAME+" (name,birthday) values ('"+name+"',"+birthday+")";db.execSQL(sql);db.close();}public void update(int id,String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象String sql = "update "+TABLENAME+" set name='"+name+"',birthday="+birthday+" where id="+id;db.execSQL(sql);db.close();}public void delete(int id){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象String sql = "delete from "+TABLENAME+" where id="+id;db.execSQL(sql);db.close();}

以上增删改三个方法写完之后,就可以在Activity当中去进行调用。

package com.example.sqliteproject;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;import com.example.sqliteopenhelper.MySQLiteOpenHelper;public class SQLiteActivity extends Activity {MySQLiteOpenHelper helper=null;Button insert,update,del = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_sqlite);insert=(Button) super.findViewById(R.id.insert);update = (Button) super.findViewById(R.id.update);del = (Button) super.findViewById(R.id.del);helper = new MySQLiteOpenHelper(this);helper.getWritableDatabase();//表示以读写的形式打开数据库insert.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.insert("毛栗子", "1995-01-05");Toast.makeText(SQLiteActivity.this, "新增成功", 0).show();}});update.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.update(1, "大白兔", "1995-01-05");Toast.makeText(SQLiteActivity.this, "修改成功", 0).show();}});del.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.delete(1);Toast.makeText(SQLiteActivity.this, "删除成功", 0).show();}});}}

以上的程序,所有数据都是固定的,这在实际开发当中显然是不科学的,因为我们至少也要使用编辑框进行数据的编辑才是符合实际,而且使用字符串拼凑sql这种形式也是存在问题的,那么我们可以使用占位符的形式来处理这种问题。

public void insert(String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象java.sql.Date date = null;try {date = new java.sql.Date(new SimpleDateFormat("yyyy-MM-dd").parse(birthday).getTime());} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();}String sql = "insert into "+TABLENAME+" (name,birthday) values (?,?)";//使用占位符Object args[] = new Object[]{name,birthday};db.execSQL(sql,args);db.close();}

对于以上程序,只是换了另一种操作方法来解决拼凑的问题,功能上没有变化。

对于拼凑sql和使用占位符,可以形成一个共识:

肯定是使用占位符更好一些。

在android当中,还对数据的封装提供了一个ContentValues类。 可以理解为一个Map集合,有key和value,唯一不同的是ContentValues中的key必须是字符串。以后的操作就可以直接通过key取得value。并将value设置到sql语句当中。

public void insert(String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象ContentValues cv = new ContentValues();cv.put("name", name);cv.put("birthday", birthday);db.insert(TABLENAME, null, cv);//进行新增操作db.close();}public void update(int id,String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象ContentValues cv = new ContentValues();cv.put("name", name);cv.put("birthday", birthday);String whereClause = " id=?";String whereArgs[]= new String[]{String.valueOf(id)};db.update(TABLENAME, cv, whereClause, whereArgs);//更新操作db.close();}public void delete(int id){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象String whereClause = " id=?";String whereArgs[]= new String[]{String.valueOf(id)};db.delete(TABLENAME, whereClause, whereArgs);//删除操作db.close();}

那么对于使用占位符和ContentValues进行数据库更新操作,两种方式并没有严格的优劣之分,但是对于不会sql的开发人员来说,使用ContentValues更好的。

·数据库查询机Cursor接口

在JDBC中ResultSet接口不呢是的功能就是依靠一个next()方法一动指针向下取数据,是到了JDBC2.0之后才能够向上取数据,但是我们一般也不去用这种向上取的形式。

Cursor接口,出现的比ResultSet晚,所有操作机制有些不同。

package com.example.sqliteproject;import java.util.ArrayList;
import java.util.List;import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;public class DH10Cursor {private static final String TABLENAME="PR10";private SQLiteDatabase db =null;public DH10Cursor(SQLiteDatabase db) {super();this.db = db;}public List<String> find(){List<String> all = new ArrayList<String>();String sql = "select id,name,birthday from "+TABLENAME;Cursor result = this.db.rawQuery(sql, null);//执行查询语句//采用循环的形式去结果集中的数据for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){all.add(result.getInt(0)+"====="+result.getString(1)+"====="+result.getString(2));}result.close();db.close();return all;}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:id="@+id/mylayout"tools:context=".SQLiteActivity" ><Buttonandroid:id="@+id/insert"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="新增"/><Buttonandroid:id="@+id/update"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="修改"/><Buttonandroid:id="@+id/del"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="删除"/><Buttonandroid:id="@+id/query"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="查询"/></LinearLayout>
package com.example.sqliteproject;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;import com.example.sqliteopenhelper.MySQLiteOpenHelper;public class SQLiteActivity extends Activity {MySQLiteOpenHelper helper=null;Button insert,update,del,query = null;ListView listView = null;LinearLayout myLayout = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_sqlite);helper = new MySQLiteOpenHelper(this);insert=(Button) super.findViewById(R.id.insert);update = (Button) super.findViewById(R.id.update);del = (Button) super.findViewById(R.id.del);query = (Button) super.findViewById(R.id.query);myLayout = (LinearLayout) super.findViewById(R.id.mylayout);query.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {SQLiteActivity.this.listView = new ListView(SQLiteActivity.this);listView.setAdapter(new ArrayAdapter<String>(SQLiteActivity.this, android.R.layout.simple_list_item_1,new DH10Cursor(SQLiteActivity.this.helper.getWritableDatabase()).find()));myLayout.addView(listView);}});insert.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.insert("毛栗子", "1995-01-05");Toast.makeText(SQLiteActivity.this, "新增成功", 0).show();}});update.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.update(1, "大白兔", "1995-01-05");Toast.makeText(SQLiteActivity.this, "修改成功", 0).show();}});del.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.delete(1);Toast.makeText(SQLiteActivity.this, "删除成功", 0).show();}});}}

需要注意一下Cursor的下标是从0开始的有别于ResultSet

·模糊查询

     ·使用sql语句完成模糊查询

public List<String> find(){List<String> all = new ArrayList<String>();String sql = "select id,name,birthday from "+TABLENAME+" where name like ?";String args[] = new String[]{"%栗%"};Cursor result = this.db.rawQuery(sql, args);//执行查询语句//采用循环的形式去结果集中的数据for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){all.add(result.getInt(0)+"====="+result.getString(1)+"====="+result.getString(2));}result.close();db.close();return all;}

        ·使用query方法完成

public List<String> find(){List<String> all = new ArrayList<String>();//String sql = "select id,name,birthday from "+TABLENAME+" where name like ?";String selection = "name like ?";String args[] = new String[]{"%栗%"};String columns[] = new String[]{"id","name","birthday"};Cursor result = this.db.query(TABLENAME, columns, selection, args, null, null, null);//执行查询语句//采用循环的形式去结果集中的数据for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){all.add(result.getInt(0)+"====="+result.getString(1)+"====="+result.getString(2));}result.close();db.close();return all;}

既然模糊查询已经能够完成了,那么还有一种功能可以往下去实现,那就是数据的分页。如果想要实现数据的部分显示,这个语句和Mysql中的查询方式是非常相似,使用limit完成。下面我们进行一些简单的分页操作。

public List<String> find(){int currentPage = 1;//当前页码int lineSize = 5;//每页显示的数据量List<String> all = new ArrayList<String>();String sql = "select id,name,birthday from "+TABLENAME+" limit ?,?";String args[] = new String[]{String.valueOf((currentPage-1)*lineSize),String.valueOf(currentPage*lineSize)};Cursor result = this.db.rawQuery(sql, args);//采用循环的形式去结果集中的数据for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){all.add(result.getInt(0)+"====="+result.getString(1)+"====="+result.getString(2));}result.close();db.close();return all;}

·使用ListView来实现滑动分页

  Android中有这样一个操作,只需要手指进行上下滑动,屏幕自动滚动,到达最后一条数据的时候,提示:请稍等,数据正在加载......。这个操作需要使用SimpleAdapter来完成,因为在这个适配器中有下面这样一个方法。

pulibc void notifyDataSetChanged()

表示如果在SimpleAdapter中的填充数据集合list内容一旦发生变化,就会立刻通知ListView进行及时新数据加载,当数据加载底部的时候,需要提示一个信息,而这个信息可以通过ListView组件里的方法去添加

public void addFooterView(View v)

现在还剩下一个问题,需要去监听滚动事件,需要使用如下接口:

首先顶一个ListView的布局模板。

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/mylayout"android:layout_width="match_parent"android:layout_height="match_parent" ><TableRow ><TextView android:id="@+id/id"android:layout_width="50px"android:layout_height="wrap_content"android:textSize="30px"/><TextView android:id="@+id/name"android:layout_width="120px"android:layout_height="wrap_content"android:textSize="30px"/><TextView android:id="@+id/birthday"android:layout_width="130px"android:layout_height="wrap_content"android:textSize="30px"/></TableRow></TableLayout>

现在我们需进行查询操作,需要返回一共有多少笔数据,修改一下查询的类

package com.example.sqliteproject;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;public class DH10Cursor {private static final String TABLENAME="DH10";private SQLiteDatabase db =null;public DH10Cursor(SQLiteDatabase db) {super();this.db = db;}public List<Map<String,Object>> find(int currentPage,int lineSize){List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();String sql = "select id,name,birthday from "+TABLENAME+" limit ?,?";String args[] = new String[]{String.valueOf((currentPage-1)*lineSize),String.valueOf(currentPage*lineSize)};Cursor result = this.db.rawQuery(sql, args);for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){Map<String,Object> map = new HashMap<String,Object>();map.put("id", result.getInt(0));map.put("name", result.getString(1));map.put("birthday", result.getString(2));list.add(map);}return list;}public int getCount(){int count = 0;String sql = "select count(id) from "+TABLENAME;Cursor result  = this.db.rawQuery(sql, null);for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){count = result.getInt(0);//取得数据的总笔数}return count;}
}

下面写一下主布局文件,这个比较简单,直接放一个线性布局管理器就可以了。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/mainlayout"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ></LinearLayout>

现在只剩下Activity

package com.example.sqliteproject;import java.util.List;
import java.util.Map;import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;import com.example.sqliteopenhelper.MySQLiteOpenHelper;public class SQLiteActivity extends Activity {MySQLiteOpenHelper helper=null;ListView listView = null;LinearLayout mainLayout = null;int currentPage = 1;int lineSize = 5;int count = 0;int pageSize = 1;//总页数int lastItem = 0;//保存最后一个记录点SimpleAdapter adapter = null;TextView tv = null;//底部信息LinearLayout loadLayout = null;//底部提示框布局List<Map<String,Object>> list = null;LayoutParams lp= new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);  super.setContentView(R.layout.listview_main);this.mainLayout=(LinearLayout) super.findViewById(R.id.mainlayout);this.loadLayout=new LinearLayout(this);this.tv = new TextView(this);tv.setText("数据加载中,请稍后。。。");tv.setGravity(Gravity.CENTER);tv.setTextSize(30);loadLayout.addView(this.tv,this.lp);loadLayout.setGravity(Gravity.CENTER);this.showAllData();}private void showAllData(){this.helper = new MySQLiteOpenHelper(this);this.listView = new ListView(this);DH10Cursor cursor = new DH10Cursor(this.helper.getWritableDatabase());//获得一个查询操作对象this.count = cursor.getCount();//取得总数据笔数this.list = cursor.find(currentPage, lineSize);this.adapter = new SimpleAdapter(this, list, R.layout.listview_item_layout, new String[]{"id","name","birthday"},new int[]{R.id.id,R.id.name,R.id.birthday});//实例化适配器对象SQLiteActivity.this.listView.addFooterView(SQLiteActivity.this.loadLayout);this.listView.setAdapter(adapter);this.listView.setOnScrollListener(new OnScrollListener() {@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if(SQLiteActivity.this.lastItem==SQLiteActivity.this.adapter.getCount()//表示当前记录已经在最底部&&SQLiteActivity.this.currentPage<SQLiteActivity.this.pageSize//当前页要小于总页数&&scrollState==OnScrollListener.SCROLL_STATE_IDLE//屏幕不再滚动){SQLiteActivity.this.currentPage++;SQLiteActivity.this.listView.setSelection(SQLiteActivity.this.lastItem);//设置显示位置SQLiteActivity.this.listView.addFooterView(SQLiteActivity.this.loadLayout);SQLiteActivity.this.appendData();}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {SQLiteActivity.this.lastItem = firstVisibleItem+visibleItemCount-1;}});mainLayout.addView(this.listView);if(this.count%this.lineSize==0){this.pageSize = this.count/this.lineSize;}else{this.pageSize = this.count/this.lineSize+1;}}private void appendData(){//更新数据方法DH10Cursor cursor = new DH10Cursor(this.helper.getWritableDatabase());List<Map<String,Object>> newData = cursor.find(currentPage, lineSize);this.list.addAll(newData);this.adapter.notifyDataSetChanged();//适配器重新加载集合数据}
}

以上就是整个实现下滑屏幕实现分页加载数据的程序。

事务的处理是针对数据库而已,以后的开发当中,只要针对增删改,都需要用事务进行处理。

public void insert(String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象db.beginTransaction();//开启事务try{ContentValues cv = new ContentValues();cv.put("name", name);cv.put("birthday", birthday);db.insert(TABLENAME, null, cv);//进行新增操作db.setTransactionSuccessful();//正确执行,否则回滚}catch(Exception e){db.endTransaction();//事务关闭db.close();}}

1.3 小结

(1)SQLite数据库是一个专门用于嵌入式设备的数据库;

(2)SQLite支持SQL语句的操作;

(3)可以使用SQLiteOpenHelper类完成数据库的操作;

(4)所有的查询数据使用Cursor进行接收;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/75475.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leangoo领歌 -敏捷任务管理软件,任务管理更轻松更透明

​任务管理&#xff0c;简单易懂&#xff0c;就是对任务进行管理。那怎么可以更好进行任务管理呢&#xff1f;怎么样样可以让任务进度可视化&#xff0c;一目了然呢&#xff1f;有效的管理可以让我们事半功倍。 接下来我们看一下如何借助任务管理软件高效的做任务管理。 首先…

Python Opencv实践 - Harris角点检测

参考资料&#xff1a;https://blog.csdn.net/wsp_1138886114/article/details/90415190 import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/chinease_tower.jpg", cv.IMREAD_COLOR) plt.imshow(img[:,:,::-1])#…

【Python】多线程

进程、线程 现代操作系统比如Mac OS X&#xff0c;UNIX&#xff0c;Linux&#xff0c;Windows等&#xff0c;都是支持“多任务”的操作系统。 进程&#xff1a;就是一个程序&#xff0c;运行在系统之上&#xff0c;那么便称之这个程序为一个运行进程&#xff0c;并分配进程ID…

【echarts】如何修改折线图X轴每个刻度的间隔宽度,让拥挤的空间变大,所有坐标点的文案可以显示得下,Echarts x轴文本内容太长的几种解决方案

Echarts 如何修改折线图X轴每个刻度的间隔宽度&#xff0c;让拥挤的空间变大&#xff0c;所有坐标点的文案可以显示得下&#xff0c;Echarts x轴文本内容太长的几种解决方案 有以下几种方案&#xff0c;堪称最全方案&#xff1a; 1、dataZoom进行坐标的比例缩放 通过调整dataZ…

设计模式篇(Java):装饰者模式

&#x1f468;‍&#x1f4bb;本文专栏&#xff1a;设计模式篇-装饰者模式 &#x1f468;‍&#x1f4bb;本文简述&#xff1a;装饰者模式的详解以及jdk中的应用 &#x1f468;‍&#x1f4bb;上一篇文章&#xff1a; 设计模式篇(Java)&#xff1a;桥接模式 &#x1f468;‍&am…

vue+element使用阿里的图标库保存图标

阿里图标网站iconfont-阿里巴巴矢量图标库 我想使用保存图标&#xff0c;但是element的图标库没有找到可用的&#xff0c;首先在阿里的图标网站搜索保存 发现这个还不错 点击添加入库 点击购物车 点击添加至项目 点击下载到本地 把下载的压缩包里面的文件拖到自己项目里面 在m…

探索多态的本质【C++】

文章目录 多态的构成条件虚函数虚函数的重写&#xff08;覆盖&#xff09; 虚函数重写的两个例外C11 override和final区分重载、覆盖(重写)、隐藏(重定义)抽象类接口继承和实现继承多态的原理虚函数表 动态绑定和静态绑定动态绑定静态绑定 单继承中的虚函数表多继承中的虚函数表…

Java——》synchronized锁升级

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…

mysql中GROUP_CONCAT函数详解

GROUP_CONCAT是MySQL中的一个聚合函数&#xff0c;它用于将多行数据按照指定的顺序连接成一个字符串&#xff0c;并返回结果。下面是对GROUP_CONCAT函数的详解&#xff1a; 语法&#xff1a; GROUP_CONCAT([DISTINCT] expr [,expr …] [ORDER BY {unsigned_integer | col_name…

Vue错误记录

文章目录 1. 项目build的时候报错Warning: Accessing non-existent property cat of module exports inside circular dependency2. WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not …

数据结构与算法之(赫夫曼树,哈夫曼树,压缩软件)

一&#xff1a;思考 1.电报发送&#xff1a;二战的时候大家都知道那时候普遍会应用电报&#xff0c;如果让你来设计一个电报的发送编码你该如何设计呢&#xff1f; 2.压缩算法&#xff1a;给你10000个字符&#xff08;每个字符1btye&#xff0c;也就是8bit&#xff09;的文件&a…

GitHub星标超70K,阿里大佬的架构总结“分布式全解”笔记霸榜

分布式架构与微服务平台是当今IT界的关键技术&#xff0c;也是资深软件工程师和系统架构师必须掌握的核心技术。 因此小编为各位粉丝朋友带来这份阿里大佬的分布式笔记&#xff1a;从传统分布式架构迁移到基于容器技术的微服务架构为主线&#xff0c;全面、透彻地介绍了与分布…

华为回击:制裁无法阻挡中国科技创新 | 百能云芯

华为最新推出的Mate 60 Pro手机引发了中国市场的抢购热潮&#xff0c;这一成功的举措为华为带来了信心。华为在这个背景下再度推出两款新机&#xff0c;其中包括高阶版的Mate 60 Pro和折叠式手机Mate X5。这两款手机在首批预购开始后迅速售罄&#xff0c;不仅取得了市场的热烈欢…

JavaScript基础

1 JavaScript概述 1.1 什么是JavaScript 1.1.1 概念 JavaScript 是脚本语言&#xff0c;是一种解释性脚本语言&#xff08;代码不进行预编译&#xff09; JavaScript 是一种轻量级的编程语言。 JavaScript 是可插入 HTML 页面的编程代码。 JavaScript 插入 HTML 页面后&a…

CANoe中的工作模式之争:由一段简单的代码引出的问题

1、引子 有网友问我一个CAPL中timer定时器的代码问题。他在CANoe工程中写了一段代码:每5秒循环触发一次定时器事件程序,输出一句文本信息到Write窗口。但是执行后发现并不是每5秒触发一次定时器事件程序,而是非常快的触发定时器事件程序。当他把这段代码复制到一个新的CANo…

【开发】安防监控/视频汇聚/云存储/AI智能视频融合平台页面新增地图模式

AI智能分析网关包含有20多种算法&#xff0c;包括人脸、人体、车辆、车牌、行为分析、烟火、入侵、聚集、安全帽、反光衣等等&#xff0c;可应用在安全生产、通用园区、智慧食安、智慧城管、智慧煤矿等场景中。将网关硬件结合我们的视频汇聚/安防监控/视频融合平台EasyCVR一起使…

2023-简单点-怎么知道树莓派是什么cpu架构?

树莓派是几位&#xff1f; getconf LONG_BIT https://qengineering.eu/install-ncnn-on-raspberry-pi-4.html

【C#】C#调用进程打开一个exe程序

文章目录 一、过程二、效果总结 一、过程 新建WinForm程序&#xff0c;并写入代码&#xff0c;明确要调用的程序的绝对路径&#xff08;或相对路径&#xff09;下的exe文件。 调用代码&#xff1a; 这里我调用的另一个程序的路径是&#xff1a; F:\WindowsFormsApplication2…

uni-app--》基于小程序开发的电商平台项目实战(一)

&#x1f3cd;️作者简介&#xff1a;大家好&#xff0c;我是亦世凡华、渴望知识储备自己的一名在校大学生 &#x1f6f5;个人主页&#xff1a;亦世凡华、 &#x1f6fa;系列专栏&#xff1a;uni-app &#x1f6b2;座右铭&#xff1a;人生亦可燃烧&#xff0c;亦可腐败&#xf…

ES6之 变量的解构赋值 ➕ 扩展运算符(…)

ES6之 变量的解构赋值 ➕ 扩展运算符 1. 变量的解构赋值1.1 直接解构赋值1.2 解构赋值——修改属性名1.3 连续解构赋值 2. 扩展运算符2.1 简介&#xff08;官网&#xff09;2.2 应用例子2.2.1 简单例子12.2.2 数组拷贝2.2.3 连接多个数组2.2.4 拷贝对象&#xff08;多层和多维数…