目录

目录

1、什么是 Truffle?

  Truffle 是最流行的开发框架,能够在本地编译、部署智能合约,使命是让开发更容易。

  Truffle 需要以太坊客户端支持,需要支持标准的JSON RPC API。

2、适合 Truffle 开发的客户端

  有许多的以太坊客户端可以选择。我们推荐在开发和部署时使用不同客户端。

  适用开发的客户端

  适用正式发布的客户端

  当开发基于 Truffle 的应用时,推荐使用EthereumJS TestRPC。它是一个完整的在内存中的区块链仅仅存在于你开发的设备上。相对于 GethTestRPC 它在执行交易时是实时返回,而不等待默认的出块时间,这样你可以快速验证你新写的代码,当出现错误时,也能即时反馈给你。它同时还是一个支持自动化测试的功能强大的客户端。Truffle 充分利用它的特性,能将测试运行时间提速近90%。

  

3、Truffle的源代码地址

  https://github.com/trufflesuite/truffle

  

4、如何安装?

  接下来的例子,我们会使用 Truffle 分别连接 GethTestRPC 测试智能合约的部署,首先我们先分别安装TruffleGethTestRPC

  

4.1、安装 Go-Ethereum 1.7.2

  Go-Ethereum 的安装参考这篇文章:使用 Go-Ethereum 1.7.2搭建以太坊私有链

  

4.2、安装 Truffle 4.0

  依赖环境:

  • NodeJS 5.0+
  • Windows,Linux,或Mac OS X

  安装很简单:

npm install -g truffle@4.0.0

  查看安装的版本:

➜ /Users/lion >truffle version
Truffle v4.0.0 (core: 4.0.0)
Solidity v0.4.18 (solc-js)

  

4.3、安装 TestRPC

➜ /Users/lion >npm install -g ethereumjs-testrpc
/usr/local/bin/testrpc -> /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js
+ ethereumjs-testrpc@6.0.1
added 1 package and updated 2 packages in 10.648s

  

5、使用 Truffle 进行智能合约的开发

5.1、初始化一个 Truffle 项目

  通过truffle init命令,可以初始化一个默认的以太坊代币合约项目,后面我们可以通过这个项目来快速学习:

➜ /Users/lion/my_project/_eth >mkdir test_truffle
➜ /Users/lion/my_project/_eth >cd test_truffle
➜ /Users/lion/my_project/_eth/test_truffle >truffle init Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet! Commands: Compile: truffle compile
Migrate: truffle migrate
Test contracts: truffle test

  完成后,你将拥有如下目录:

  • contracts 智能合约目录
  • migrations 发布脚本目录
  • test 存放测试文件
  • truffle.js Truffle的配置文件

  

5.2、编译合约

  要编译合约,使用truffle compile命令,可以将原始代码编译成以太坊认可的字节码:

➜ /Users/lion/my_project/_eth/test_truffle >truffle compile
Compiling ./contracts/Migrations.sol...
Writing artifacts to ./build/contracts

  Truffle仅默认编译自上次编译后被修改过的文件,来减少不必要的编译。如果你想编译全部文件,可以使用--compile-all选项

truffle compile --compile-all

  Truffle需要定义的合约名称和文件名准确匹配,这种匹配是区分大小写的,也就是说大小写也要一致。推荐大写每一个开头字母。

  文件之间的相互依赖,可以使用import进行合约间的引用,Truffle将会按正确顺序依次编译合约,并在需要的时候自动关联库。例如:

import "./AnotherContract.sol";

  

5.3、创建一个 Hello mshk.top 的合约并编译

  在contracts目录中新建一个Hello_mshk_top.sol文件,代码如下:

pragma solidity ^0.4.17;

contract Hello_mshk_top {

  //say hello mshk.top
function say() public pure returns (string) {
return "Hello mshk.top";
} //print name
function print(string name) public pure returns (string) {
return name;
}
}

  代码中有两个方法:say()方法是输出一段文字Hello mshk.topprint(string name)方法是输出传入的内容。

  编辑migrations/1_initial_migration.js部署脚本,将我们刚才创建的Hello_mshk_top.sol文件设置到发布配置文件中,内容如下:

var Migrations = artifacts.require("./Migrations.sol");
var Hello_mshk_top = artifacts.require("./Hello_mshk_top.sol");
module.exports = function(deployer) {
deployer.deploy(Migrations);
deployer.deploy(Hello_mshk_top);
};

  将项目使用truffle compile命令进行编译,编译后的文件都放在了./build/contracts目录下:

➜ /Users/lion/my_project/_eth/test_truffle >truffle compile
Compiling ./contracts/Hello_mshk_top.sol...
Compiling ./contracts/Migrations.sol...
Writing artifacts to ./build/contracts

  Hello_mshk_top.sol编译后的文件是./build/contracts/Hello_mshk_top.json中,后面在部署到geth中,我们会用到。

  

6、部署智能合约

  编辑truffle.js配置文件,设置我们稍后要部署智能合约的位置,内容如下:

module.exports = {
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*"
}
}
};

  接下来,我们会使用上面的智能合约,分别在testRPCgeth中进行部署测试。

  truffle的智能合约项目部署,使用下面的命令:

truffle migrate

  这个命令会执行所有migrations目录下的js文件。如果之前执行过truffle migrate命令,再次执行,只会部署新的js文件,如果没有新的js文件,不会起任何作用。如果使用--reset参数,则会重新的执行所有脚本的部署。

  如果要部署到指定的网络,可以使用--network参数,例如:

truffle migrate --network live

  多个网络的配置格式如下:

networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*" // match any network
},
live: {
host: "178.25.19.88", // Random IP for example purposes (do not use)
port: 80,
network_id: 1, // Ethereum public network
// optional config values:
// gas Gas limit used for deploys. Default is 4712388
// gasPrice Gas price used for deploys. Default is 100000000000 (100 Shannon).
// from - default address to use for any transaction Truffle makes during migrations
// provider - web3 provider instance Truffle should use to talk to the Ethereum network.
// - if specified, host and port are ignored.
}
}

  

6.1、将智能合约部署到 TestRPC 中测试

6.1.2、启动 TestRPC

  直接输入testrpc命令,就可以调用起 TestRPC 客户端,启动 testrpc 经后,会默认创建10个帐号,Available Accounts是帐号列表,Private Keys是相对应的帐号密钥:

➜ /Users/lion >testrpc --gasLimit 0x800000000
EthereumJS TestRPC v6.0.1 (ganache-core: 2.0.0) Available Accounts
==================
(0) 0x74650142c29e358b8f94a8c5d43345649009a4cd
...... Private Keys
==================
(0) f11fa29910cd639aeb6de6126f2f16e091c1da51956fefccafca0afc476fbc41
......
HD Wallet
==================
Mnemonic: inquiry sense exit ice craft evoke april gym settle social cat uniform
Base HD Path: m/44'/60'/0'/0'/{account_index} Gas Limit
==================
34359738368 Listening on localhost:8545

  

6.1.3、通过 truffle migrate 命令,对合约进行部署

  使用truffle migrate命令,发布项目:

➜ /Users/lion/my_project/_eth/test_truffle >truffle migrate
Using network 'development'. Running migration: 1_initial_migration.js
Deploying Migrations...
... 0xd9e5fa242d29362e57e3da7b0bf6f71b72767972fc15240ed3a02d341e814a44
Migrations: 0x4bedd1bb517ff9a54f6f3df8eba821ff16a4109b
Deploying Hello_mshk_top...
... 0xc22ff050e189c2561d40250077ee4bf628f957899dfa8d0b5fa50e3ab7a896b0
Hello_mshk_top: 0xa7ef5037ff81d7932e01b68a503ca4587f00b35c
Saving successful migration to network...
... 0x49505a54042f5f74146fbfafef63dd408cb0a7a0c66214ebbaa3217e443d792a
Saving artifacts...

  

6.1.4、测试部署成功的智能合约

  输入以下命令打开truffle控制台,测试刚才我们部署的Hello_mshk_top合约:

truffle(development)> var contract;
undefined
truffle(development)> Hello_mshk_top.deployed().then(function(instance){contract= instance;});
undefined
truffle(development)> contract.say()
'Hello mshk.top'
truffle(development)> contract.print("https://mshk.top")
'https://mshk.top'

  var contractjavascript语法一样,表示声明一个contract变量。Hello_mshk_top.deployed().then(function(instance){contract= instance;})表示,将Hello_mshk_top合约主体,传递给contract变量。后面我们就可以直接使用变量contract分别调用say()方法和print(''),得到我们想要的结果。

  

6.2、将智能合约部署到 Geth 1.7.2 私有链

6.2.1、新建 Geth 的创世区块文件,并初始化

  新建一个test_truffle_geth目录,同时新建我们的创世区块文件genesis.json

➜ /Users/lion/my_project/_eth >mkdir test_truffle_geth
➜ /Users/lion/my_project/_eth >cd test_truffle_geth
➜ /Users/lion/my_project/_eth/test_truffle_geth >vi genesis.json

  genesis.json:

{
"config": {
"chainId": 10,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
"extraData" : "",
"gasLimit" : "0x8000000",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00",
"alloc": {}
}

  初始化创世区块

➜ /Users/lion/my_project/_eth/test_truffle_geth >geth init ./genesis.json --datadir "./chain"
WARN [11-07|10:17:11] No etherbase set and no accounts found as default
INFO [11-07|10:17:11] Allocated cache and file handles database=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/chaindata cache=16 handles=16
INFO [11-07|10:17:11] Writing custom genesis block
INFO [11-07|10:17:11] Successfully wrote genesis state database=chaindata hash=ecf271…5269d6
INFO [11-07|10:17:11] Allocated cache and file handles database=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/lightchaindata cache=16 handles=16
INFO [11-07|10:17:11] Writing custom genesis block
INFO [11-07|10:17:11] Successfully wrote genesis state database=lightchaindata hash=ecf271…5269d6

  

6.2.2、使用 RPC 方式运行 Geth

  使用rpc方式运行geth

➜ /Users/lion/my_project/_eth/test_truffle_geth >geth \
--identity "mshk.top etherum" \
--rpcaddr 0.0.0.0 \
--rpc \
--rpcport 8545 \
--maxpeers 2 \
--rpcapi "db,eth,net,web3,debug" \
--networkid 100 \
--datadir "./chain" \
--nodiscover
WARN [11-07|10:21:56] No etherbase set and no accounts found as default
INFO [11-07|10:21:56] Starting peer-to-peer node instance="Geth/mshk.top etherum/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9.1"
INFO [11-07|10:21:56] Allocated cache and file handles database=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/chaindata cache=128 handles=1024
WARN [11-07|10:21:56] Upgrading database to use lookup entries
INFO [11-07|10:21:56] Initialised chain configuration config="{ChainID: 10 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Byzantium: <nil> Engine: unknown}"
INFO [11-07|10:21:56] Disk storage enabled for ethash caches dir=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/ethash count=3
INFO [11-07|10:21:56] Disk storage enabled for ethash DAGs dir=/Users/lion/.ethash count=2
INFO [11-07|10:21:56] Initialising Ethereum protocol versions="[63 62]" network=100
INFO [11-07|10:21:56] Database deduplication successful deduped=0
INFO [11-07|10:21:56] Loaded most recent local header number=0 hash=ecf271…5269d6 td=131072
INFO [11-07|10:21:56] Loaded most recent local full block number=0 hash=ecf271…5269d6 td=131072
INFO [11-07|10:21:56] Loaded most recent local fast block number=0 hash=ecf271…5269d6 td=131072
INFO [11-07|10:21:56] Regenerated local transaction journal transactions=0 accounts=0
INFO [11-07|10:21:56] Starting P2P networking
INFO [11-07|10:21:56] RLPx listener up self="enode://eee1025474554baf3d42dc72fb6f13df8246b5ed879ca6a7764d3147c422ca2d10eba1dc6a9e609d3535794668d1e064548550683a8c34cfefbcf879b9cbaf2b@[::]:30303?discport=0"
INFO [11-07|10:21:56] IPC endpoint opened: /Users/lion/my_project/_eth/test_truffle_geth/chain/geth.ipc
INFO [11-07|10:21:56] HTTP endpoint opened: http://0.0.0.0:8545
INFO [11-07|10:21:56] Mapped network port proto=tcp extport=30303 intport=30303 interface=NAT-PMP(10.0.0.1)

  

  启动私有节点需要的参数:

参数名称 参数描述
identity 区块链的标示,随便填写,用于标示目前网络的名字
init 指定创世块文件的位置,并创建初始块
datadir 设置当前区块链网络数据存放的位置
port 网络监听端口 默认是30303
rpc 启动rpc通信,可以进行智能合约的部署和调试
maxpeers 网络节点的最大数量,默认是25
rpcapi 设置允许连接的rpc的客户端,一般为db,eth,net,web3
networkid 设置当前区块链的网络ID,用于区分不同的网络,是一个数字
console 启动命令行模式,可以在Geth中执行命令
dev 开发者模式,带调试模式的专有网络
nodiscover 私有链地址,不会被网上看到

  

  rpc方式启动geth以后,会一直停止在那里,没有办法在geth中进行任何输入。浏览一下我们刚才创建区块链数据的文件夹,会发现有一个geth.ipc文件。

➜ /Users/lion >ll /Users/lion/my_project/_eth/test_truffle_geth/chain
total 0
drwxr-xr-x 7 lion staff 224 Nov 7 10:21 geth
srw------- 1 lion staff 0 Nov 7 10:21 geth.ipc
drwx------ 2 lion staff 64 Nov 7 10:17 keystore

  然后用下面这个命令,进入geth控制台:

➜ /Users/lion >geth attach ipc://Users/lion/my_project/_eth/test_truffle_geth/chain/geth.ipc
Welcome to the Geth JavaScript console! instance: Geth/mshk.top etherum/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9.1
modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0 >

  

6.2.3、在 Geth 中新建帐户,开始挖矿

  创建一个帐户,并解锁用户一段时间(单位是秒),然后启动挖矿

> web3.personal.newAccount("123456")
"0x0a67659a161410a4a1e0a5889ff05a1417915172"
> personal.unlockAccount(eth.accounts[0], "123456", 15000)
true
> miner.start(1)
null

  过一会后查看下帐户地址的余额,将帐户地址赋值给变量acc0,可以看到里面有了以太币:

> acc0 = web3.eth.accounts[0]
"0xc90747b99362c41fa89d2e7dea1b5b8d9567b741"
> web3.eth.getBalance(acc0)
415000000000000000000

  

6.2.4、在 Geth 中部署合约

  这时,我们就要用到刚刚编译后的Hello_mshk_top.json文件了,打开https://www.bejson.com网址,把abi部分取出并转义。然后在geth中输入以下内容,将json转义后的内容,赋值给mshk_abi变量:

mshk_abi=JSON.parse('[{\"constant\":true,\"inputs\":[{\"name\":\"name\",\"type\":\"string\"}],\"name\":\"print\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"say\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}]')

  会得到下面的返回值:

[{
constant: true,
inputs: [{
name: "name",
type: "string"
}],
name: "print",
outputs: [{
name: "",
type: "string"
}],
payable: false,
stateMutability: "pure",
type: "function"
}, {
constant: true,
inputs: [],
name: "say",
outputs: [{
name: "",
type: "string"
}],
payable: false,
stateMutability: "pure",
type: "function"
}]

  找到Hello_mshk_top.json文件中的bytecode部分,然后在geth中,将值赋值给mshk_bytecode变量,在geth中输入以下内容:

mshk_bytecode="0x6060604052341561000f57600080fd5b6102488061001e6000396000f30060606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806311114af114610051578063954ab4b214610127575b600080fd5b341561005c57600080fd5b6100ac600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506101b5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100ec5780820151818401526020810190506100d1565b50505050905090810190601f1680156101195780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013257600080fd5b61013a6101c5565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561017a57808201518184015260208101905061015f565b50505050905090810190601f1680156101a75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101bd610208565b819050919050565b6101cd610208565b6040805190810160405280600e81526020017f48656c6c6f206d73686b2e746f70000000000000000000000000000000000000815250905090565b6020604051908101604052806000815250905600a165627a7a72305820aa448d81e0f4bf12f805920c9cefd0d3cc6f053d87dd8547663721256179ebcd0029"

  评估下创建合约需要的手续费是207296gas

> web3.eth.estimateGas({data: mshk_bytecode})
207296

  部署合约,并将合约传递给mshk变量,在geth中输入以下内容:

mshk_Contract = web3.eth.contract(abi);
mshk_hello = mshk_Contract.new({from:acc0, data:mshk_bytecode, gas:300000}, function(e, contract){
if(!e) { if(!contract.address) {
console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined..."); } else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
} }
});

  输入成功后,会看到下面的信息,0x1d055281899007cbe6865a48d0a79239dac8e486是合约创建成功的地址:

> Contract mined! Address: 0x1d055281899007cbe6865a48d0a79239dac8e486
[object Object]

  

6.2.5、测试部署成功的智能合约

  恭喜你,如果能看到上面的信息,说明智能合约已经部署成功了。接下来,我们可以使用下面的命令在geth中调用,刚刚部署成功的合约:

> mshk_hello.say()
"Hello mshk.top"
> mshk_hello.print("Hello https://mshk.top")
"Hello https://mshk.top"

  通过这些章节的练习,你可以将之前章节中的代币合约、众筹合约进行部署。

  

7、代币合约、高级代币合约、众筹合约项目地址

  文章中使用的完整代码,存放在了github上面:https://github.com/idoall/truffle_solidity_contractsExample

  

8、扩展阅读

upgrading-from-truffle-2-to-3

Full Stack Hello World Voting Ethereum Dapp Tutorial

Truffle Documentation

Building a smart contract using the command line

truffle3.0-integrate-nodejs


博文作者:迦壹

博客地址:Truffle 4.0、Geth 1.7.2、TestRPC在私有链上搭建智能合约

转载声明:可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明,谢谢合作!


Truffle 4.0、Geth 1.7.2、TestRPC在私有链上搭建智能合约的更多相关文章

  1. 在testrpc以太坊测试环境部署智能合约

    2018年03月13日 09:20:54 思无邪-machengyu 阅读数 2683   版权声明:本文为博主原创文章,转载请务必注明出处,否则追究法律责任 https://blog.csdn.ne ...

  2. Go-Ethereum 1.7.2 结合 Mist 0.9.2 实现代币智能合约的实例

    目录 目录 1.什么是 Mist 2.Mist 在哪里下载? 3.Mist 有哪些依赖? 4.如何安装 Mist? 4.1.安装 Mist 依赖工具包 4.2.安装 Mist 4.3.启动 Mist, ...

  3. 使用Truffle 部署智能合约

    使用Truffle 部署智能合约 之前我们使用Geth,原生的以太坊Golang工具,分析了创世区块的参数内容,在本地创建了私有以太坊区块链,并使用两个账户进行了挖矿和转账操作,对以太坊有了基本了解. ...

  4. 区块链学习(四)truffle部署编译智能合约以太坊私有链

    前面我们介绍了以太坊私有链的搭建以及多节点私有链网络,这次我们介绍如何使用truffle框架来部署编译智能合约到我们之前搭建的私有链网络中. 搭建环境及需使用的工具:ubuntu18.04  Truf ...

  5. nodejs部署智能合约的方法-web3 0.20版本

    参考:https://www.jianshu.com/p/7e541cd67be2 部署智能合约的方法有很多,比如使用truffle框架,使用remix-ide等,在这里的部署方法是使用nodejs一 ...

  6. Remix+Geth 实现智能合约部署和调用详解

    Remix编写智能合约 编写代码 在线调试 实现部署 调用接口 Geth实现私有链部署合约和调用接口 部署合约 调用合约 获得合约实例 通过实例调用合约接口 Remix编写智能合约 编写代码 Remi ...

  7. Mac下基于testrpc和truffle的以太坊智能合约开发环境搭建

    原文地址:石匠的blog truffle是一个基于Javascript开发的一套智能合约开发框架,使用Solidity语言编写合约.truffle有一套自动的项目构建机制,集成了开发,测试和部署的各个 ...

  8. 区块链入门(5)Truffle 项目实战,Solidity IDE, 智能合约部署

    在上一张我们学习了Truffle项目的创建,部署等相关内容,今天我们就来实战一下. 今天我们要做3件事: 1) 学习搭建一个Solidity IDE(Remix). 2) 使用这个Solidity I ...

  9. truffle 发布 智能合约

    参考 这篇https://www.codeooze.com/blockchain/ethereum-geth-private-blockchain/ 说的已经很详细了 genesis.json 过时了 ...

随机推荐

  1. [Swift]LeetCode247.对称数 II $ Strobogrammatic Number II

    A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside ...

  2. Java引入的一些新特性

    Java引入的一些新特性 Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本. Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程, ...

  3. 浅谈React

    浅谈react react是什么?其官网给出了明确定义:A JavaScript library for building user interfaces,一个用于构建用户界面的JavaScript库 ...

  4. mongo 根据对象中的某个条件来查询

    假如A表有如下数据 { "id" : 1, "users_info" : [{"uid" : 10001}, {"uid" ...

  5. visual studio git for coding

    直接放图吧 双击存储库项目进入Git操作页面 点击之后输入你要发布的git地址 选择你的操作 如果你登录的密码错了 就需要去修改 否则永远都pull失败 打开控制面板 在这里修改

  6. RabbitMQ学习笔记(三) 发布与订阅

    发布与订阅 在我们使用手机发送消息的时候,即可以选择给单个手机号码发送消息,也可以选择多个手机号码,群发消息. 前面学习工作队列的时候,我们使用的场景是一个消息只能被一个消费者程序实例接收并处理,但是 ...

  7. golang子进程的启动和停止,mac与linux的区别

    今天接到一个任务是将原来运行在mac的应用移植到linux,原因当然是因为客户那边当前是linux环境,也不想再采购mac电脑. 通常来说,这个工作并不难,因为我选用的服务器端技术是c或者golang ...

  8. 【Android】打开本地的html文件

    网上好多说法 但实际上说到点上的没有 不想写太长 直接进入正题 Intent intent = new Intent(Intent.ACTION_VIEW); intent.addCategory(I ...

  9. [十]JavaIO之FilterInputStream FilterOutputStream

    FilterInputStream  FilterOutputStream都是装饰器模式中的Decorator抽象装饰角色 他们继承了各自的抽象构建InputStream 和OutputStream ...

  10. eclipse svn插件卸载 重新安装 Subclipse卸载安装 The project was not built since its build path is incomplete This client is too old to work with the working copy at

    安装插件的原则就是,要按照规则,插件与本地的svn版本要一致, 这样子本地和eclipse上面就可以无缝使用,不会出现问题 1.卸载eclipse  svn插件 2,安装新版的svn插件 2.1,下载 ...