package test;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class FileReadWriteTest {
public static void main(String[] args) throws IOException {
String filePath = "D:\\MyTextFileTest.txt";
new File(filePath).createNewFile();
writeFileContent_1(filePath, true, "中文字測試");
writeFileContent_1(filePath, true, "你好哈囉");
System.out.println(readFileContent_1(filePath));
System.out.println(readFileContent_2(filePath));
}
/*************** Write File ***************/
public static void writeFileContent_1(String filePath, boolean isAppend, String contentToWrite) {
try (
FileOutputStream fileOutputStream = new FileOutputStream(new File(filePath), isAppend);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
){
bufferedWriter.write(contentToWrite);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeFileContent_2(String filePath, boolean isAppend, String contentToWrite) {
try {
if (isAppend) {
Files.writeString(Paths.get(filePath), contentToWrite, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
}else {
Files.writeString(Paths.get(filePath), contentToWrite, StandardCharsets.UTF_8);
}
} catch (IOException e) {
e.printStackTrace();
}
}
/*************** Read File ***************/
public static String readFileContent_1(String filePath) {
StringBuffer fileContent = new StringBuffer();
try (
FileInputStream fileInputStream = new FileInputStream(new File(filePath));
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
) {
String readContent = "";
while ((readContent = bufferedReader.readLine()) != null) {
fileContent.append(readContent + "\n");
}
if (fileContent.length() > 0) {
//remove the latest added "\n"
fileContent.deleteCharAt(fileContent.length() - 1);
}
} catch (IOException e) {
e.printStackTrace();
}
return fileContent.toString();
}
public static String readFileContent_2(String filePath) {
String fileContent = "";
try {
fileContent = Files.readString(Paths.get(filePath), StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
return fileContent;
}
}
2021年12月3日 星期五
Java 讀取寫入文字檔案的幾種方法
2021年11月26日 星期五
得到瀏覽器 scrollbar 寬度
Get the Scrollbar Width of an Element
const scrollbarWidth = document.body.offsetWidth - document.body.clientWidth;
參考:
https://www.javascripttutorial.net/dom/css/get-the-scrollbar-width-of-an-element/
Note:
2021/11/26
不知道為什麼,現在發現
document.body.offsetWidth 會等於 document.body.clientWidth,
不過研究了一下 Bootstrap Modal 的程式源碼,
發現可以用
window.innerWidth - document.documentElement.clientWidth
來得到正確的 scrollbarWidth
原因不明,或許跟 web 標準改變有關??
2021年7月1日 星期四
[MS sql server] 使用 Sql 語法在不同 database 中間倒資料的方法
在登入一個 sql server下,
可以用以下語法存取另一個 sql server,
例如以下語法可以登入名為 xxxServer, port 為 1300 的 sql server
exec sp_addlinkedserver 'myXxxServer', '', 'SQLOLEDB', 'xxxServer,1300' -- create linked server to xxxServer
exec sp_addlinkedsrvlogin 'myXxxServer', 'false',null, '{帳號}', '{密碼}' -- login xxxServer
然後就可以用 myXxxServer 這個名字 (可自取) 存取 xxxServer,
例如讀取其中的一個名為 xxxTable 的 table,其 table 在名為 xxxDatabase 的 database 中:
SELECT * FROM myXxxServer.xxxDatabase.dbo.xxxTable
還可以做到跨 sql server 的 JOIN 等操作,非常方便,例如:
SELECT * FROM myXxxServer.xxxDatabase.dbo.xxxTable A INNER JOIN someTable B ON A.a = B.b
或是倒資料,例如:
INSERT INTO A(a1, a2) SELECT b1, b2 FROM myXxxServer.xxxDatabase.dbo.B
最後再用以下語法登出 xxxServer
exec sp_dropserver 'myXxxServer', 'droplogins' -- free myXxxServer linked server
**補充:
如果要倒的資料欄位裡有主鍵 (Primary Key),
需要把禁止修改主鍵的功能關掉,Update 資料完後再開回來。
再來此時不能用星號 "*" 來代表所有欄位,要把欄位名稱一個個寫出來才能成功寫入。
例如:
SET IDENTITY_INSERT A ON; INSERT INTO A(a1, a2) SELECT b1, b2 FROM myXxxServer.xxxDatabase.dbo.B SET IDENTITY_INSERT A OFF;
如果想要快速的得到欄位名稱的字串,可以用以下語法來得到
(以下為得到名為 A 這個 table 的所有欄位名稱,會用逗號分隔欄位名,最後用成一串字來輸出):
SELECT SUBSTRING(
(
SELECT ', ' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'A'
ORDER BY ORDINAL_POSITION
FOR XML path('')
)
, 3, 200000
)
執行結果就像是: [a1], [a2], [a3]
2021年3月30日 星期二
Docker 練習 - 安裝 Tomcat - 設定 virtualBox 的 Port Forwarding
docker pull tomcat:9.0-jdk11-openjdk
# 所以想要看觀迎頁面可以自己手動把頁面放到 /usr/local/tomcat/webapps 下
Linux - Docker 和 docker-compose 的好用指令記錄 - 學習紀錄
使用 Linux Ubuntu 為例子。
#可在 Windows 上用 PowerShell 安裝 WSL (預設安裝 WSL2),參考 安裝 WSL | Microsoft Learn
wsl --install
- docker.io
- docker-compose
- docker-compose-v2
- docker-doc
- docker-buildx
- podman-docker
#設定 Dokcer apt repository
# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl status docker
2021年3月29日 星期一
Linux - virtual box share folder 的設定
在 Windows 中,使用 virtual box 安裝好 Ubuntu 64 server 後,
如果想方便的分享 Windows 的資料夾給 Virtual box 開啟的 VM 使用,
可以使用 VirtualBox 的 "共用資料夾" 功能。
下面示範步驟
--------------------------------------------------------------------------
安裝 VirtualBox Guest Additions :
在 Virutalbox 開啟的 VM 視窗上選擇 "裝置" --> "插入 Guest Additions CD 像"
建立資料夾 (資料夾可自訂) : mkdir -p /mnt/cdrom
掛載光碟機上去 : mount /dev/cdrom /mnt/cdrom
進入光碟機:cd /mnt/cdrom
安裝 VirtualBox Guest Additions: sh ./VBoxLinuxAdditions.run --nox11
--------------------------------------------------------------------------
接著先把 VM 關機,在 Virtualbox 上對此VM做共用資料夾的設定:"設定" --> "共用資料夾"
可以在 Windows 端中放檔案,或在 VM 中放檔案,應該都可在各自端的地方看到共用檔案的變化了。
參考:
2021年2月7日 星期日
Minecraft Java 版 (1.16.4, jdk 1.8) 自製 Forge Mod - 實作物品、合成表、物品特殊效果
- 其物品類別為 "戰鬥 (Combat)" 物品。
- 其有自己的名字 (英文叫 Super Sword,中文叫超級劍)。
- 其為"劍 (Sword)"這個物品的客制版本,有自己的攻擊傷害等數值。
- 其有自己的2D圖示,並拿此圖示做為 3D 時的樣子 (例如玩家拿在手上的樣子)。
- 其被玩家拿在手上時,有自己效果,此例為玩家不會受到攻擊及效果傷害,並且攻擊者會受到最大生命值一半的傷害。
package com.my.mode.item;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.IItemTier;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.Rarity;
import net.minecraft.item.SwordItem;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.living.LivingAttackEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
public class SuperSword extends SwordItem{
public final static String ITEM_ID = "super_sword";
public SuperSword() {
super(new IItemTier() {
@Override
public int getMaxUses() {
// TODO Auto-generated method stub
return 100;
}
@Override
public float getEfficiency() {
// TODO Auto-generated method stub
return 0;
}
@Override
public float getAttackDamage() {
// TODO Auto-generated method stub
return 100;
}
@Override
public int getHarvestLevel() {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getEnchantability() {
// TODO Auto-generated method stub
return 0;
}
@Override
public Ingredient getRepairMaterial() {
// TODO Auto-generated method stub
return null;
}
}, 100, 1, (new Item.Properties()).group(ItemGroup.COMBAT));
}
@SubscribeEvent
public void onLivingAttackEvent(LivingAttackEvent event) {
LivingEntity livingEntity = event.getEntityLiving();
World world = livingEntity.getEntityWorld();
if(!world.isRemote && livingEntity instanceof PlayerEntity) {
PlayerEntity playerEntity = (PlayerEntity) livingEntity;
if (playerEntity.getHeldItemMainhand().getItem() instanceof SuperSword
|| playerEntity.getHeldItemOffhand().getItem() instanceof SuperSword) {
//把事件取消,效果為攻擊無效,不會愛傷
event.setCanceled(true);
//增加效果,效果為對攻擊玩家 (player) 的生物造成傷害
if (event.getSource().getTrueSource() instanceof LivingEntity) {
LivingEntity attacker = (LivingEntity) event.getSource().getTrueSource();
attacker.attackEntityFrom(DamageSource.GENERIC, attacker.getMaxHealth() / 2);
}
}
}
}
@SubscribeEvent
public void onLivingAttackEvent(LivingHurtEvent event) {
LivingEntity livingEntity = event.getEntityLiving();
World world = livingEntity.getEntityWorld();
if(!world.isRemote && livingEntity instanceof PlayerEntity) {
PlayerEntity playerEntity = (PlayerEntity) livingEntity;
if (playerEntity.getHeldItemMainhand().getItem() instanceof SuperSword
|| playerEntity.getHeldItemOffhand().getItem() instanceof SuperSword) {
//把事件取消,效果為傷害無效,不會愛傷
event.setCanceled(true);
}
}
}
}
在 SuperSword.java 的建構子 (constructor) 中,SuperSword 繼承了 SwordItem,
net.minecraft.item.SwordItem.SwordItem(IItemTier tier, int attackDamageIn, float attackSpeedIn, Properties builderIn)
LivingEntity livingEntity = event.getEntityLiving();
if (playerEntity.getHeldItemMainhand().getItem() instanceof SuperSword || playerEntity.getHeldItemOffhand().getItem() instanceof SuperSword)
if (event.getSource().getTrueSource() instanceof LivingEntity) {
LivingEntity attacker = (LivingEntity) event.getSource().getTrueSource();
attacker.attackEntityFrom(DamageSource.GENERIC, attacker.getMaxHealth() / 2);
}
package com.my.mode.item;
import com.my.mode.MyMod;
import net.minecraft.item.Item;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
public class Items {
private static DeferredRegister<Item> REGISTER = null;
public static DeferredRegister<Item> getRegister(){
if (REGISTER == null) {
REGISTER = DeferredRegister.create(ForgeRegistries.ITEMS, MyMod.MOD_ID);
}
//注冊自製物品
REGISTER.register(SuperSword.ITEM_ID, () -> new SuperSword());
return REGISTER;
}
}
package com.my.mode;
import com.my.mode.item.Items;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
public class ModEventBusHandler {
public static void register() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.register(ModEventBusHandler.class);
modEventBus.register(new ModEventBusHandler());
//註冊自製物品,並將其註冊到 ModEventBus 中
Items.getRegister().register(modEventBus);
}
@SubscribeEvent
public void onCommonSetupEvent(FMLCommonSetupEvent event) {
ForgeEventBusHandler.register();
}
}
Items.getRegister().register(modEventBus);
package com.my.mode;
import com.my.mode.item.SuperSword;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.monster.MonsterEntity;
import net.minecraft.entity.passive.FoxEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.item.ItemTossEvent;
import net.minecraftforge.event.entity.living.LivingAttackEvent;
import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
public class ForgeEventBusHandler {
public static void register() {
IEventBus forgeEventBus = MinecraftForge.EVENT_BUS;
forgeEventBus.register(ForgeEventBusHandler.class);
forgeEventBus.register(new ForgeEventBusHandler());
//註冊超級劍 (super sword) 的事件效果
forgeEventBus.register(new SuperSword());
forgeEventBus.register(SuperSword.class);
}
// Event 有分成在 ModEventUs 上的,或在 ForgeEventBus 上的,
// 此例的 ItemTossEvent 為在 ForgeEventBus 上的 Event
@SubscribeEvent
public void onItemTossEvent(ItemTossEvent event) {
//ItemTossEvent: 物品丟棄時觸發的 Event,
//在遊戲中可用按鍵 q 來丟棄物品
ItemEntity item = event.getEntityItem();
World world = item.getEntityWorld();
if (!world.isRemote) { // 判斷是否為 logical server 端,即處理邏輯的那端
// 如果此例的 isRemote 為 true,即為 logical client 端
// 可參考
// https://hackmd.io/@immortalmice/Hkj9s-CvU/https%3A%2F%2Fhackmd.io%2F%40immortalmice%2FrJKayrf9U
//建立一個狐狸物件
FoxEntity fox = new FoxEntity(EntityType.FOX, world);
fox.setPosition(item.getPosX(), item.getPosY(), item.getPosZ());
//將物件放到世界中
world.addEntity(fox);
}
}
}
forgeEventBus.register(new SuperSword()); forgeEventBus.register(SuperSword.class);
Note:
forgeEventBus.register(new SuperSword()); 用來註冊 SuperSword 裡的 non-static method,forgeEventBus.register(SuperSword.class); 用來註冊 SuperSwrod 裡的 static method。
{
"item.mymod.super_sword": "Super Sword"
}{
"item.mymod.super_sword": "超級劍"
}{
"parent": "item/generated",
"textures": {
"layer0": "mymod:item/super_sword"
},
"display": {
"thirdperson_righthand": {
"rotation": [0, 90, 0],
"translation" : [0, 3, 0],
"scale" : [1, 1, 1]
}
}
}Note:
此時如果把 SuperSword 拿在左手,會發現一樣如拿在右手上一樣有吃到調整的設定,應該是因為當有設定右手時,如果左手沒設定的話會自動以右手設定為準。
{
"type": "minecraft:crafting_shaped",
"pattern":
[
" x ",
"xxx",
" x "
],
"key":
{
"x":
{
"item": "minecraft:dirt"
}
},
"result":
{
"item": "mymod:super_sword",
"count": 1
}
}






